svf-tools 1.0.285 → 1.0.286
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.TXT +6 -4
- package/SVF-doxygen/html/html/dir_63dba4c559aa5986900c35e27974bafc.html +83 -0
- package/SVF-doxygen/html/html/dir_97aefd0d527b934f1d99a682da8fe6a9.html +2 -0
- package/SVF-doxygen/html/html/dir_d1b325ac671111a54e189ae033ba710d.html +87 -0
- package/SVF-doxygen/html/html/dir_d44c64559bbebec7f509842c48db8b23.html +2 -0
- package/SVF-doxygen/html/html/fastcluster_8cpp.html +263 -0
- package/SVF-doxygen/html/html/fastcluster_8cpp_source.html +88 -0
- package/SVF-doxygen/html/html/fastcluster_8h.html +278 -0
- package/SVF-doxygen/html/html/fastcluster_8h_source.html +86 -0
- package/SVF-doxygen/html/html/fastcluster__R__dm_8cpp_8inc.html +79 -0
- package/SVF-doxygen/html/html/fastcluster__R__dm_8cpp_8inc_source.html +77 -0
- package/SVF-doxygen/html/html/fastcluster__dm_8cpp_8inc.html +89 -0
- package/SVF-doxygen/html/html/fastcluster__dm_8cpp_8inc_source.html +80 -0
- package/SVF-doxygen/html/html/files.html +220 -214
- package/SVF-doxygen/html/html/globals_c.html +82 -74
- package/SVF-doxygen/html/html/globals_enum.html +3 -0
- package/SVF-doxygen/html/html/globals_eval.html +19 -0
- package/SVF-doxygen/html/html/globals_f.html +6 -3
- package/SVF-doxygen/html/html/globals_func_c.html +46 -38
- package/SVF-doxygen/html/html/globals_func_f.html +3 -0
- package/SVF-doxygen/html/html/globals_func_h.html +4 -0
- package/SVF-doxygen/html/html/globals_h.html +22 -0
- package/SVF-doxygen/html/html/globals_r.html +3 -3
- package/SVF-doxygen/html/html/globals_s.html +7 -9
- package/SVF-doxygen/html/html/menudata.js +1 -0
- package/SVF-doxygen/html/html/search/all_12.js +1 -1
- package/SVF-doxygen/html/html/search/all_13.js +4 -4
- package/SVF-doxygen/html/html/search/all_3.js +2 -0
- package/SVF-doxygen/html/html/search/all_6.js +5 -0
- package/SVF-doxygen/html/html/search/all_8.js +7 -0
- package/SVF-doxygen/html/html/search/enums_4.js +1 -2
- package/SVF-doxygen/html/html/search/enums_5.js +2 -2
- package/SVF-doxygen/html/html/search/enums_6.js +2 -3
- package/SVF-doxygen/html/html/search/enums_7.js +3 -6
- package/SVF-doxygen/html/html/search/enums_8.js +6 -1
- package/SVF-doxygen/html/html/search/enums_9.js +1 -5
- package/SVF-doxygen/html/html/search/enums_a.js +5 -1
- package/SVF-doxygen/html/html/search/enums_b.js +1 -4
- package/SVF-doxygen/html/html/search/enums_c.html +26 -0
- package/SVF-doxygen/html/html/search/enums_c.js +7 -0
- package/SVF-doxygen/html/html/search/enumvalues_7.js +5 -0
- package/SVF-doxygen/html/html/search/files_5.js +4 -0
- package/SVF-doxygen/html/html/search/functions_2.js +2 -0
- package/SVF-doxygen/html/html/search/functions_5.js +1 -0
- package/SVF-doxygen/html/html/search/functions_7.js +1 -0
- package/SVF-doxygen/html/html/search/searchdata.js +1 -1
- package/include/FastCluster/LICENSE.TXT +13 -0
- package/include/FastCluster/fastcluster.h +79 -0
- package/lib/CMakeLists.txt +4 -1
- package/lib/FastCluster/LICENSE.TXT +13 -0
- package/lib/FastCluster/fastcluster.cpp +170 -0
- package/lib/FastCluster/fastcluster_R_dm.cpp.inc +115 -0
- package/lib/FastCluster/fastcluster_dm.cpp.inc +1795 -0
- package/package.json +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
3
|
+
<head>
|
|
4
|
+
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
|
6
|
+
<meta name="generator" content="Doxygen 1.8.13"/>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
8
|
+
<title>Static Value-Flow Analysis: /home/runner/work/SVF/SVF/lib/FastCluster/fastcluster_dm.cpp.inc Source File</title>
|
|
9
|
+
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
|
10
|
+
<script type="text/javascript" src="jquery.js"></script>
|
|
11
|
+
<script type="text/javascript" src="dynsections.js"></script>
|
|
12
|
+
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
|
13
|
+
<script type="text/javascript" src="search/searchdata.js"></script>
|
|
14
|
+
<script type="text/javascript" src="search/search.js"></script>
|
|
15
|
+
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|
19
|
+
<div id="titlearea">
|
|
20
|
+
<table cellspacing="0" cellpadding="0">
|
|
21
|
+
<tbody>
|
|
22
|
+
<tr style="height: 56px;">
|
|
23
|
+
<td id="projectalign" style="padding-left: 0.5em;">
|
|
24
|
+
<div id="projectname">Static Value-Flow Analysis
|
|
25
|
+
</div>
|
|
26
|
+
</td>
|
|
27
|
+
</tr>
|
|
28
|
+
</tbody>
|
|
29
|
+
</table>
|
|
30
|
+
</div>
|
|
31
|
+
<!-- end header part -->
|
|
32
|
+
<!-- Generated by Doxygen 1.8.13 -->
|
|
33
|
+
<script type="text/javascript">
|
|
34
|
+
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
|
35
|
+
</script>
|
|
36
|
+
<script type="text/javascript" src="menudata.js"></script>
|
|
37
|
+
<script type="text/javascript" src="menu.js"></script>
|
|
38
|
+
<script type="text/javascript">
|
|
39
|
+
$(function() {
|
|
40
|
+
initMenu('',true,false,'search.php','Search');
|
|
41
|
+
$(document).ready(function() { init_search(); });
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
<div id="main-nav"></div>
|
|
45
|
+
<!-- window showing the filter options -->
|
|
46
|
+
<div id="MSearchSelectWindow"
|
|
47
|
+
onmouseover="return searchBox.OnSearchSelectShow()"
|
|
48
|
+
onmouseout="return searchBox.OnSearchSelectHide()"
|
|
49
|
+
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- iframe showing the search results (closed by default) -->
|
|
53
|
+
<div id="MSearchResultsWindow">
|
|
54
|
+
<iframe src="javascript:void(0)" frameborder="0"
|
|
55
|
+
name="MSearchResults" id="MSearchResults">
|
|
56
|
+
</iframe>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div id="nav-path" class="navpath">
|
|
60
|
+
<ul>
|
|
61
|
+
<li class="navelem"><a class="el" href="dir_97aefd0d527b934f1d99a682da8fe6a9.html">lib</a></li><li class="navelem"><a class="el" href="dir_d1b325ac671111a54e189ae033ba710d.html">FastCluster</a></li> </ul>
|
|
62
|
+
</div>
|
|
63
|
+
</div><!-- top -->
|
|
64
|
+
<div class="header">
|
|
65
|
+
<div class="headertitle">
|
|
66
|
+
<div class="title">fastcluster_dm.cpp.inc</div> </div>
|
|
67
|
+
</div><!--header-->
|
|
68
|
+
<div class="contents">
|
|
69
|
+
<a href="fastcluster__dm_8cpp_8inc.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> <span class="comment">/*</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span> <span class="comment"> fastcluster: Fast hierarchical clustering routines for R and Python</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span> <span class="comment"></span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span> <span class="comment"> Copyright © 2011 Daniel Müllner</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span> <span class="comment"> <http://danifold.net></span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span> <span class="comment"></span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span> <span class="comment"> This library implements various fast algorithms for hierarchical,</span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span> <span class="comment"> agglomerative clustering methods:</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span> <span class="comment"></span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span> <span class="comment"> (1) Algorithms for the "stored matrix approach": the input is the array of</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span> <span class="comment"> pairwise dissimilarities.</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span> <span class="comment"></span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span> <span class="comment"> MST_linkage_core: single linkage clustering with the "minimum spanning</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span> <span class="comment"> tree algorithm (Rohlfs)</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span> <span class="comment"></span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span> <span class="comment"> NN_chain_core: nearest-neighbor-chain algorithm, suitable for single,</span></div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span> <span class="comment"> complete, average, weighted and Ward linkage (Murtagh)</span></div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span> <span class="comment"></span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span> <span class="comment"> generic_linkage: generic algorithm, suitable for all distance update</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span> <span class="comment"> formulas (Müllner)</span></div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span> <span class="comment"></span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span> <span class="comment"> (2) Algorithms for the "stored data approach": the input are points in a</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span> <span class="comment"> vector space.</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span> <span class="comment"></span></div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span> <span class="comment"> MST_linkage_core_vector: single linkage clustering for vector data</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span> <span class="comment"></span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span> <span class="comment"> generic_linkage_vector: generic algorithm for vector data, suitable for</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span> <span class="comment"> the Ward, centroid and median methods.</span></div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span> <span class="comment"></span></div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span> <span class="comment"> generic_linkage_vector_alternative: alternative scheme for updating the</span></div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span> <span class="comment"> nearest neighbors. This method seems faster than "generic_linkage_vector"</span></div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span> <span class="comment"> for the centroid and median methods but slower for the Ward method.</span></div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span> <span class="comment"></span></div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span> <span class="comment"> All these implementation treat infinity values correctly. They throw an</span></div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span> <span class="comment"> exception if a NaN distance value occurs.</span></div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span> <span class="comment">*/</span></div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span> </div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span> <span class="comment">// Older versions of Microsoft Visual Studio do not have the fenv header.</span></div><div class="line"><a name="l00039"></a><span class="lineno"> 39</span> <span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><a name="l00040"></a><span class="lineno"> 40</span> <span class="preprocessor">#if (_MSC_VER == 1500 || _MSC_VER == 1600)</span></div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span> <span class="preprocessor">#define NO_INCLUDE_FENV</span></div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span> <span class="comment">// NaN detection via fenv might not work on systems with software</span></div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span> <span class="comment">// floating-point emulation (bug report for Debian armel).</span></div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span> <span class="preprocessor">#ifdef __SOFTFP__</span></div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span> <span class="preprocessor">#define NO_INCLUDE_FENV</span></div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span> <span class="preprocessor">#ifdef NO_INCLUDE_FENV</span></div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span> <span class="comment">// #pragma message("Do not use fenv header.")</span></div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span> <span class="comment">// #pragma message("Use fenv header. If there is a warning about unknown #pragma STDC FENV_ACCESS, this can be ignored.")</span></div><div class="line"><a name="l00053"></a><span class="lineno"> 53</span> <span class="comment">// TODO</span></div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span> <span class="comment">//#pragma STDC FENV_ACCESS ON</span></div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span> <span class="preprocessor">#include <fenv.h></span></div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span> </div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span> <span class="preprocessor">#include <cmath></span> <span class="comment">// for std::pow, std::sqrt</span></div><div class="line"><a name="l00059"></a><span class="lineno"> 59</span> <span class="preprocessor">#include <cstddef></span> <span class="comment">// for std::ptrdiff_t</span></div><div class="line"><a name="l00060"></a><span class="lineno"> 60</span> <span class="preprocessor">#include <limits></span> <span class="comment">// for std::numeric_limits<...>::infinity()</span></div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span> <span class="preprocessor">#include <algorithm></span> <span class="comment">// for std::fill_n</span></div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span> <span class="preprocessor">#include <stdexcept></span> <span class="comment">// for std::runtime_error</span></div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span> <span class="preprocessor">#include <string></span> <span class="comment">// for std::string</span></div><div class="line"><a name="l00064"></a><span class="lineno"> 64</span> </div><div class="line"><a name="l00065"></a><span class="lineno"> 65</span> <span class="preprocessor">#include <cfloat></span> <span class="comment">// also for DBL_MAX, DBL_MIN</span></div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span> <span class="preprocessor">#ifndef DBL_MANT_DIG</span></div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span> <span class="preprocessor">#error The constant DBL_MANT_DIG could not be defined.</span></div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00069"></a><span class="lineno"> 69</span> <span class="preprocessor">#define T_FLOAT_MANT_DIG DBL_MANT_DIG</span></div><div class="line"><a name="l00070"></a><span class="lineno"> 70</span> </div><div class="line"><a name="l00071"></a><span class="lineno"> 71</span> <span class="preprocessor">#ifndef LONG_MAX</span></div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span> <span class="preprocessor">#include <climits></span></div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span> <span class="preprocessor">#ifndef LONG_MAX</span></div><div class="line"><a name="l00075"></a><span class="lineno"> 75</span> <span class="preprocessor">#error The constant LONG_MAX could not be defined.</span></div><div class="line"><a name="l00076"></a><span class="lineno"> 76</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span> <span class="preprocessor">#ifndef INT_MAX</span></div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span> <span class="preprocessor">#error The constant INT_MAX could not be defined.</span></div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00080"></a><span class="lineno"> 80</span> </div><div class="line"><a name="l00081"></a><span class="lineno"> 81</span> <span class="preprocessor">#ifndef INT32_MAX</span></div><div class="line"><a name="l00082"></a><span class="lineno"> 82</span> <span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><a name="l00083"></a><span class="lineno"> 83</span> <span class="preprocessor">#if _MSC_VER >= 1600</span></div><div class="line"><a name="l00084"></a><span class="lineno"> 84</span> <span class="preprocessor">#define __STDC_LIMIT_MACROS</span></div><div class="line"><a name="l00085"></a><span class="lineno"> 85</span> <span class="preprocessor">#include <stdint.h></span></div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00087"></a><span class="lineno"> 87</span> <span class="keyword">typedef</span> __int32 int_fast32_t;</div><div class="line"><a name="l00088"></a><span class="lineno"> 88</span> <span class="keyword">typedef</span> __int64 int64_t;</div><div class="line"><a name="l00089"></a><span class="lineno"> 89</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00090"></a><span class="lineno"> 90</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00091"></a><span class="lineno"> 91</span> <span class="preprocessor">#define __STDC_LIMIT_MACROS</span></div><div class="line"><a name="l00092"></a><span class="lineno"> 92</span> <span class="preprocessor">#include <stdint.h></span></div><div class="line"><a name="l00093"></a><span class="lineno"> 93</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00094"></a><span class="lineno"> 94</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00095"></a><span class="lineno"> 95</span> </div><div class="line"><a name="l00096"></a><span class="lineno"> 96</span> <span class="preprocessor">#define FILL_N std::fill_n</span></div><div class="line"><a name="l00097"></a><span class="lineno"> 97</span> <span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><a name="l00098"></a><span class="lineno"> 98</span> <span class="preprocessor">#if _MSC_VER < 1600</span></div><div class="line"><a name="l00099"></a><span class="lineno"> 99</span> <span class="preprocessor">#undef FILL_N</span></div><div class="line"><a name="l00100"></a><span class="lineno"> 100</span> <span class="preprocessor">#define FILL_N stdext::unchecked_fill_n</span></div><div class="line"><a name="l00101"></a><span class="lineno"> 101</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00102"></a><span class="lineno"> 102</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00103"></a><span class="lineno"> 103</span> </div><div class="line"><a name="l00104"></a><span class="lineno"> 104</span> <span class="comment">// Suppress warnings about (potentially) uninitialized variables.</span></div><div class="line"><a name="l00105"></a><span class="lineno"> 105</span> <span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><a name="l00106"></a><span class="lineno"> 106</span> <span class="preprocessor"> #pragma warning (disable:4700)</span></div><div class="line"><a name="l00107"></a><span class="lineno"> 107</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00108"></a><span class="lineno"> 108</span> </div><div class="line"><a name="l00109"></a><span class="lineno"> 109</span> <span class="preprocessor">#ifndef HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00110"></a><span class="lineno"> 110</span> <span class="preprocessor">#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))</span></div><div class="line"><a name="l00111"></a><span class="lineno"> 111</span> <span class="preprocessor">#define HAVE_DIAGNOSTIC 1</span></div><div class="line"><a name="l00112"></a><span class="lineno"> 112</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00113"></a><span class="lineno"> 113</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00114"></a><span class="lineno"> 114</span> </div><div class="line"><a name="l00115"></a><span class="lineno"> 115</span> <span class="preprocessor">#ifndef HAVE_VISIBILITY</span></div><div class="line"><a name="l00116"></a><span class="lineno"> 116</span> <span class="preprocessor">#if __GNUC__ >= 4</span></div><div class="line"><a name="l00117"></a><span class="lineno"> 117</span> <span class="preprocessor">#define HAVE_VISIBILITY 1</span></div><div class="line"><a name="l00118"></a><span class="lineno"> 118</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00119"></a><span class="lineno"> 119</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span> </div><div class="line"><a name="l00121"></a><span class="lineno"> 121</span> <span class="comment">/* Since the public interface is given by the Python respectively R interface,</span></div><div class="line"><a name="l00122"></a><span class="lineno"> 122</span> <span class="comment"> * we do not want other symbols than the interface initalization routines to be</span></div><div class="line"><a name="l00123"></a><span class="lineno"> 123</span> <span class="comment"> * visible in the shared object file. The "visibility" switch is a GCC concept.</span></div><div class="line"><a name="l00124"></a><span class="lineno"> 124</span> <span class="comment"> * Hiding symbols keeps the relocation table small and decreases startup time.</span></div><div class="line"><a name="l00125"></a><span class="lineno"> 125</span> <span class="comment"> * See http://gcc.gnu.org/wiki/Visibility</span></div><div class="line"><a name="l00126"></a><span class="lineno"> 126</span> <span class="comment"> */</span></div><div class="line"><a name="l00127"></a><span class="lineno"> 127</span> <span class="preprocessor">#if HAVE_VISIBILITY</span></div><div class="line"><a name="l00128"></a><span class="lineno"> 128</span> <span class="preprocessor">#pragma GCC visibility push(hidden)</span></div><div class="line"><a name="l00129"></a><span class="lineno"> 129</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00130"></a><span class="lineno"> 130</span> </div><div class="line"><a name="l00131"></a><span class="lineno"> 131</span> <span class="keyword">typedef</span> int_fast32_t t_index;</div><div class="line"><a name="l00132"></a><span class="lineno"> 132</span> <span class="preprocessor">#ifndef INT32_MAX</span></div><div class="line"><a name="l00133"></a><span class="lineno"> 133</span> <span class="preprocessor">#define MAX_INDEX 0x7fffffffL</span></div><div class="line"><a name="l00134"></a><span class="lineno"> 134</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00135"></a><span class="lineno"> 135</span> <span class="preprocessor">#define MAX_INDEX INT32_MAX</span></div><div class="line"><a name="l00136"></a><span class="lineno"> 136</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00137"></a><span class="lineno"> 137</span> <span class="preprocessor">#if (LONG_MAX < MAX_INDEX)</span></div><div class="line"><a name="l00138"></a><span class="lineno"> 138</span> <span class="preprocessor">#error The integer format "t_index" must not have a greater range than "long int".</span></div><div class="line"><a name="l00139"></a><span class="lineno"> 139</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00140"></a><span class="lineno"> 140</span> <span class="preprocessor">#if (INT_MAX > MAX_INDEX)</span></div><div class="line"><a name="l00141"></a><span class="lineno"> 141</span> <span class="preprocessor">#error The integer format "int" must not have a greater range than "t_index".</span></div><div class="line"><a name="l00142"></a><span class="lineno"> 142</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00143"></a><span class="lineno"> 143</span> <span class="keyword">typedef</span> <span class="keywordtype">double</span> t_float;</div><div class="line"><a name="l00144"></a><span class="lineno"> 144</span> </div><div class="line"><a name="l00145"></a><span class="lineno"> 145</span> <span class="comment">/* Method codes.</span></div><div class="line"><a name="l00146"></a><span class="lineno"> 146</span> <span class="comment"></span></div><div class="line"><a name="l00147"></a><span class="lineno"> 147</span> <span class="comment"> These codes must agree with the METHODS array in fastcluster.R and the</span></div><div class="line"><a name="l00148"></a><span class="lineno"> 148</span> <span class="comment"> dictionary mthidx in fastcluster.py.</span></div><div class="line"><a name="l00149"></a><span class="lineno"> 149</span> <span class="comment">*/</span></div><div class="line"><a name="l00150"></a><span class="lineno"> 150</span> <span class="keyword">enum</span> method_codes {</div><div class="line"><a name="l00151"></a><span class="lineno"> 151</span>  <span class="comment">// non-Euclidean methods</span></div><div class="line"><a name="l00152"></a><span class="lineno"> 152</span>  METHOD_METR_SINGLE = 0,</div><div class="line"><a name="l00153"></a><span class="lineno"> 153</span>  METHOD_METR_COMPLETE = 1,</div><div class="line"><a name="l00154"></a><span class="lineno"> 154</span>  METHOD_METR_AVERAGE = 2,</div><div class="line"><a name="l00155"></a><span class="lineno"> 155</span>  METHOD_METR_WEIGHTED = 3,</div><div class="line"><a name="l00156"></a><span class="lineno"> 156</span>  METHOD_METR_WARD = 4,</div><div class="line"><a name="l00157"></a><span class="lineno"> 157</span>  METHOD_METR_WARD_D = METHOD_METR_WARD,</div><div class="line"><a name="l00158"></a><span class="lineno"> 158</span>  METHOD_METR_CENTROID = 5,</div><div class="line"><a name="l00159"></a><span class="lineno"> 159</span>  METHOD_METR_MEDIAN = 6,</div><div class="line"><a name="l00160"></a><span class="lineno"> 160</span>  METHOD_METR_WARD_D2 = 7,</div><div class="line"><a name="l00161"></a><span class="lineno"> 161</span> </div><div class="line"><a name="l00162"></a><span class="lineno"> 162</span>  MIN_METHOD_CODE = 0,</div><div class="line"><a name="l00163"></a><span class="lineno"> 163</span>  MAX_METHOD_CODE = 7</div><div class="line"><a name="l00164"></a><span class="lineno"> 164</span> };</div><div class="line"><a name="l00165"></a><span class="lineno"> 165</span> </div><div class="line"><a name="l00166"></a><span class="lineno"> 166</span> <span class="keyword">enum</span> method_codes_vector {</div><div class="line"><a name="l00167"></a><span class="lineno"> 167</span>  <span class="comment">// Euclidean methods</span></div><div class="line"><a name="l00168"></a><span class="lineno"> 168</span>  METHOD_VECTOR_SINGLE = 0,</div><div class="line"><a name="l00169"></a><span class="lineno"> 169</span>  METHOD_VECTOR_WARD = 1,</div><div class="line"><a name="l00170"></a><span class="lineno"> 170</span>  METHOD_VECTOR_CENTROID = 2,</div><div class="line"><a name="l00171"></a><span class="lineno"> 171</span>  METHOD_VECTOR_MEDIAN = 3,</div><div class="line"><a name="l00172"></a><span class="lineno"> 172</span> </div><div class="line"><a name="l00173"></a><span class="lineno"> 173</span>  MIN_METHOD_VECTOR_CODE = 0,</div><div class="line"><a name="l00174"></a><span class="lineno"> 174</span>  MAX_METHOD_VECTOR_CODE = 3</div><div class="line"><a name="l00175"></a><span class="lineno"> 175</span> };</div><div class="line"><a name="l00176"></a><span class="lineno"> 176</span> </div><div class="line"><a name="l00177"></a><span class="lineno"> 177</span> <span class="comment">// self-destructing array pointer</span></div><div class="line"><a name="l00178"></a><span class="lineno"> 178</span> <span class="keyword">template</span> <<span class="keyword">typename</span> type></div><div class="line"><a name="l00179"></a><span class="lineno"> 179</span> <span class="keyword">class </span>auto_array_ptr{</div><div class="line"><a name="l00180"></a><span class="lineno"> 180</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00181"></a><span class="lineno"> 181</span>  type * ptr;</div><div class="line"><a name="l00182"></a><span class="lineno"> 182</span>  auto_array_ptr(auto_array_ptr <span class="keyword">const</span> &); <span class="comment">// non construction-copyable</span></div><div class="line"><a name="l00183"></a><span class="lineno"> 183</span>  auto_array_ptr& operator=(auto_array_ptr <span class="keyword">const</span> &); <span class="comment">// non copyable</span></div><div class="line"><a name="l00184"></a><span class="lineno"> 184</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00185"></a><span class="lineno"> 185</span>  auto_array_ptr()</div><div class="line"><a name="l00186"></a><span class="lineno"> 186</span>  : ptr(NULL)</div><div class="line"><a name="l00187"></a><span class="lineno"> 187</span>  { }</div><div class="line"><a name="l00188"></a><span class="lineno"> 188</span>  <span class="keyword">template</span> <<span class="keyword">typename</span> index></div><div class="line"><a name="l00189"></a><span class="lineno"> 189</span>  auto_array_ptr(index <span class="keyword">const</span> size)</div><div class="line"><a name="l00190"></a><span class="lineno"> 190</span>  : ptr(new type[size])</div><div class="line"><a name="l00191"></a><span class="lineno"> 191</span>  { }</div><div class="line"><a name="l00192"></a><span class="lineno"> 192</span>  <span class="keyword">template</span> <<span class="keyword">typename</span> index, <span class="keyword">typename</span> value></div><div class="line"><a name="l00193"></a><span class="lineno"> 193</span>  auto_array_ptr(index <span class="keyword">const</span> size, value <span class="keyword">const</span> val)</div><div class="line"><a name="l00194"></a><span class="lineno"> 194</span>  : ptr(new type[size])</div><div class="line"><a name="l00195"></a><span class="lineno"> 195</span>  {</div><div class="line"><a name="l00196"></a><span class="lineno"> 196</span>  FILL_N(ptr, size, val);</div><div class="line"><a name="l00197"></a><span class="lineno"> 197</span>  }</div><div class="line"><a name="l00198"></a><span class="lineno"> 198</span>  ~auto_array_ptr() {</div><div class="line"><a name="l00199"></a><span class="lineno"> 199</span>  <span class="keyword">delete</span> [] ptr; }</div><div class="line"><a name="l00200"></a><span class="lineno"> 200</span>  <span class="keywordtype">void</span> <a class="code" href="util_8h.html#a3110dcad20c2a6616d360901b94e06a1">free</a>() {</div><div class="line"><a name="l00201"></a><span class="lineno"> 201</span>  <span class="keyword">delete</span> [] ptr;</div><div class="line"><a name="l00202"></a><span class="lineno"> 202</span>  ptr = NULL;</div><div class="line"><a name="l00203"></a><span class="lineno"> 203</span>  }</div><div class="line"><a name="l00204"></a><span class="lineno"> 204</span>  <span class="keyword">template</span> <<span class="keyword">typename</span> index></div><div class="line"><a name="l00205"></a><span class="lineno"> 205</span>  <span class="keywordtype">void</span> init(index <span class="keyword">const</span> size) {</div><div class="line"><a name="l00206"></a><span class="lineno"> 206</span>  ptr = <span class="keyword">new</span> type [size];</div><div class="line"><a name="l00207"></a><span class="lineno"> 207</span>  }</div><div class="line"><a name="l00208"></a><span class="lineno"> 208</span>  <span class="keyword">template</span> <<span class="keyword">typename</span> index, <span class="keyword">typename</span> value></div><div class="line"><a name="l00209"></a><span class="lineno"> 209</span>  <span class="keywordtype">void</span> init(index <span class="keyword">const</span> size, value <span class="keyword">const</span> val) {</div><div class="line"><a name="l00210"></a><span class="lineno"> 210</span>  init(size);</div><div class="line"><a name="l00211"></a><span class="lineno"> 211</span>  FILL_N(ptr, size, val);</div><div class="line"><a name="l00212"></a><span class="lineno"> 212</span>  }</div><div class="line"><a name="l00213"></a><span class="lineno"> 213</span>  <span class="keyword">inline</span> <span class="keyword">operator</span> type *() <span class="keyword">const</span> { <span class="keywordflow">return</span> ptr; }</div><div class="line"><a name="l00214"></a><span class="lineno"> 214</span> };</div><div class="line"><a name="l00215"></a><span class="lineno"> 215</span> </div><div class="line"><a name="l00216"></a><span class="lineno"> 216</span> <span class="keyword">struct </span>node {</div><div class="line"><a name="l00217"></a><span class="lineno"> 217</span>  t_index node1, node2;</div><div class="line"><a name="l00218"></a><span class="lineno"> 218</span>  t_float dist;</div><div class="line"><a name="l00219"></a><span class="lineno"> 219</span> };</div><div class="line"><a name="l00220"></a><span class="lineno"> 220</span> </div><div class="line"><a name="l00221"></a><span class="lineno"> 221</span> <span class="keyword">inline</span> <span class="keywordtype">bool</span> operator< (<span class="keyword">const</span> node a, <span class="keyword">const</span> node b) {</div><div class="line"><a name="l00222"></a><span class="lineno"> 222</span>  <span class="keywordflow">return</span> (a.dist < b.dist);</div><div class="line"><a name="l00223"></a><span class="lineno"> 223</span> }</div><div class="line"><a name="l00224"></a><span class="lineno"> 224</span> </div><div class="line"><a name="l00225"></a><span class="lineno"> 225</span> <span class="keyword">class </span>cluster_result {</div><div class="line"><a name="l00226"></a><span class="lineno"> 226</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00227"></a><span class="lineno"> 227</span>  auto_array_ptr<node> Z;</div><div class="line"><a name="l00228"></a><span class="lineno"> 228</span>  t_index pos;</div><div class="line"><a name="l00229"></a><span class="lineno"> 229</span> </div><div class="line"><a name="l00230"></a><span class="lineno"> 230</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00231"></a><span class="lineno"> 231</span>  cluster_result(<span class="keyword">const</span> t_index size)</div><div class="line"><a name="l00232"></a><span class="lineno"> 232</span>  : Z(size)</div><div class="line"><a name="l00233"></a><span class="lineno"> 233</span>  , pos(0)</div><div class="line"><a name="l00234"></a><span class="lineno"> 234</span>  {}</div><div class="line"><a name="l00235"></a><span class="lineno"> 235</span> </div><div class="line"><a name="l00236"></a><span class="lineno"> 236</span>  <span class="keywordtype">void</span> append(<span class="keyword">const</span> t_index node1, <span class="keyword">const</span> t_index node2, <span class="keyword">const</span> t_float dist) {</div><div class="line"><a name="l00237"></a><span class="lineno"> 237</span>  Z[pos].node1 = node1;</div><div class="line"><a name="l00238"></a><span class="lineno"> 238</span>  Z[pos].node2 = node2;</div><div class="line"><a name="l00239"></a><span class="lineno"> 239</span>  Z[pos].dist = dist;</div><div class="line"><a name="l00240"></a><span class="lineno"> 240</span>  ++pos;</div><div class="line"><a name="l00241"></a><span class="lineno"> 241</span>  }</div><div class="line"><a name="l00242"></a><span class="lineno"> 242</span> </div><div class="line"><a name="l00243"></a><span class="lineno"> 243</span>  node * operator[] (<span class="keyword">const</span> t_index idx)<span class="keyword"> const </span>{ <span class="keywordflow">return</span> Z + idx; }</div><div class="line"><a name="l00244"></a><span class="lineno"> 244</span> </div><div class="line"><a name="l00245"></a><span class="lineno"> 245</span>  <span class="comment">/* Define several methods to postprocess the distances. All these functions</span></div><div class="line"><a name="l00246"></a><span class="lineno"> 246</span> <span class="comment"> are monotone, so they do not change the sorted order of distances. */</span></div><div class="line"><a name="l00247"></a><span class="lineno"> 247</span> </div><div class="line"><a name="l00248"></a><span class="lineno"> 248</span>  <span class="keywordtype">void</span> sqrt()<span class="keyword"> const </span>{</div><div class="line"><a name="l00249"></a><span class="lineno"> 249</span>  <span class="keywordflow">for</span> (node * ZZ=Z; ZZ!=Z+pos; ++ZZ) {</div><div class="line"><a name="l00250"></a><span class="lineno"> 250</span>  ZZ->dist = std::sqrt(ZZ->dist);</div><div class="line"><a name="l00251"></a><span class="lineno"> 251</span>  }</div><div class="line"><a name="l00252"></a><span class="lineno"> 252</span>  }</div><div class="line"><a name="l00253"></a><span class="lineno"> 253</span> </div><div class="line"><a name="l00254"></a><span class="lineno"> 254</span>  <span class="keywordtype">void</span> sqrt(<span class="keyword">const</span> t_float)<span class="keyword"> const </span>{ <span class="comment">// ignore the argument</span></div><div class="line"><a name="l00255"></a><span class="lineno"> 255</span>  sqrt();</div><div class="line"><a name="l00256"></a><span class="lineno"> 256</span>  }</div><div class="line"><a name="l00257"></a><span class="lineno"> 257</span> </div><div class="line"><a name="l00258"></a><span class="lineno"> 258</span>  <span class="keywordtype">void</span> sqrtdouble(<span class="keyword">const</span> t_float)<span class="keyword"> const </span>{ <span class="comment">// ignore the argument</span></div><div class="line"><a name="l00259"></a><span class="lineno"> 259</span>  <span class="keywordflow">for</span> (node * ZZ=Z; ZZ!=Z+pos; ++ZZ) {</div><div class="line"><a name="l00260"></a><span class="lineno"> 260</span>  ZZ->dist = std::sqrt(2*ZZ->dist);</div><div class="line"><a name="l00261"></a><span class="lineno"> 261</span>  }</div><div class="line"><a name="l00262"></a><span class="lineno"> 262</span>  }</div><div class="line"><a name="l00263"></a><span class="lineno"> 263</span> </div><div class="line"><a name="l00264"></a><span class="lineno"> 264</span> <span class="preprocessor"> #ifdef R_pow</span></div><div class="line"><a name="l00265"></a><span class="lineno"> 265</span> <span class="preprocessor"> #define my_pow R_pow</span></div><div class="line"><a name="l00266"></a><span class="lineno"> 266</span> <span class="preprocessor"> #else</span></div><div class="line"><a name="l00267"></a><span class="lineno"> 267</span> <span class="preprocessor"> #define my_pow std::pow</span></div><div class="line"><a name="l00268"></a><span class="lineno"> 268</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00269"></a><span class="lineno"> 269</span> </div><div class="line"><a name="l00270"></a><span class="lineno"> 270</span>  <span class="keywordtype">void</span> power(<span class="keyword">const</span> t_float p)<span class="keyword"> const </span>{</div><div class="line"><a name="l00271"></a><span class="lineno"> 271</span>  t_float <span class="keyword">const</span> q = 1/p;</div><div class="line"><a name="l00272"></a><span class="lineno"> 272</span>  <span class="keywordflow">for</span> (node * ZZ=Z; ZZ!=Z+pos; ++ZZ) {</div><div class="line"><a name="l00273"></a><span class="lineno"> 273</span>  ZZ->dist = my_pow(ZZ->dist,q);</div><div class="line"><a name="l00274"></a><span class="lineno"> 274</span>  }</div><div class="line"><a name="l00275"></a><span class="lineno"> 275</span>  }</div><div class="line"><a name="l00276"></a><span class="lineno"> 276</span> </div><div class="line"><a name="l00277"></a><span class="lineno"> 277</span>  <span class="keywordtype">void</span> plusone(<span class="keyword">const</span> t_float)<span class="keyword"> const </span>{ <span class="comment">// ignore the argument</span></div><div class="line"><a name="l00278"></a><span class="lineno"> 278</span>  <span class="keywordflow">for</span> (node * ZZ=Z; ZZ!=Z+pos; ++ZZ) {</div><div class="line"><a name="l00279"></a><span class="lineno"> 279</span>  ZZ->dist += 1;</div><div class="line"><a name="l00280"></a><span class="lineno"> 280</span>  }</div><div class="line"><a name="l00281"></a><span class="lineno"> 281</span>  }</div><div class="line"><a name="l00282"></a><span class="lineno"> 282</span> </div><div class="line"><a name="l00283"></a><span class="lineno"> 283</span>  <span class="keywordtype">void</span> divide(<span class="keyword">const</span> t_float denom)<span class="keyword"> const </span>{</div><div class="line"><a name="l00284"></a><span class="lineno"> 284</span>  <span class="keywordflow">for</span> (node * ZZ=Z; ZZ!=Z+pos; ++ZZ) {</div><div class="line"><a name="l00285"></a><span class="lineno"> 285</span>  ZZ->dist /= denom;</div><div class="line"><a name="l00286"></a><span class="lineno"> 286</span>  }</div><div class="line"><a name="l00287"></a><span class="lineno"> 287</span>  }</div><div class="line"><a name="l00288"></a><span class="lineno"> 288</span> };</div><div class="line"><a name="l00289"></a><span class="lineno"> 289</span> </div><div class="line"><a name="l00290"></a><span class="lineno"> 290</span> <span class="keyword">class </span>doubly_linked_list {</div><div class="line"><a name="l00291"></a><span class="lineno"> 291</span>  <span class="comment">/*</span></div><div class="line"><a name="l00292"></a><span class="lineno"> 292</span> <span class="comment"> Class for a doubly linked list. Initially, the list is the integer range</span></div><div class="line"><a name="l00293"></a><span class="lineno"> 293</span> <span class="comment"> [0, size]. We provide a forward iterator and a method to delete an index</span></div><div class="line"><a name="l00294"></a><span class="lineno"> 294</span> <span class="comment"> from the list.</span></div><div class="line"><a name="l00295"></a><span class="lineno"> 295</span> <span class="comment"></span></div><div class="line"><a name="l00296"></a><span class="lineno"> 296</span> <span class="comment"> Typical use: for (i=L.start; L<size; i=L.succ[I])</span></div><div class="line"><a name="l00297"></a><span class="lineno"> 297</span> <span class="comment"> or</span></div><div class="line"><a name="l00298"></a><span class="lineno"> 298</span> <span class="comment"> for (i=somevalue; L<size; i=L.succ[I])</span></div><div class="line"><a name="l00299"></a><span class="lineno"> 299</span> <span class="comment"> */</span></div><div class="line"><a name="l00300"></a><span class="lineno"> 300</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00301"></a><span class="lineno"> 301</span>  t_index start;</div><div class="line"><a name="l00302"></a><span class="lineno"> 302</span>  auto_array_ptr<t_index> succ;</div><div class="line"><a name="l00303"></a><span class="lineno"> 303</span> </div><div class="line"><a name="l00304"></a><span class="lineno"> 304</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00305"></a><span class="lineno"> 305</span>  auto_array_ptr<t_index> pred;</div><div class="line"><a name="l00306"></a><span class="lineno"> 306</span>  <span class="comment">// Not necessarily private, we just do not need it in this instance.</span></div><div class="line"><a name="l00307"></a><span class="lineno"> 307</span> </div><div class="line"><a name="l00308"></a><span class="lineno"> 308</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00309"></a><span class="lineno"> 309</span>  doubly_linked_list(<span class="keyword">const</span> t_index size)</div><div class="line"><a name="l00310"></a><span class="lineno"> 310</span>  <span class="comment">// Initialize to the given size.</span></div><div class="line"><a name="l00311"></a><span class="lineno"> 311</span>  : start(0)</div><div class="line"><a name="l00312"></a><span class="lineno"> 312</span>  , succ(size+1)</div><div class="line"><a name="l00313"></a><span class="lineno"> 313</span>  , pred(size+1)</div><div class="line"><a name="l00314"></a><span class="lineno"> 314</span>  {</div><div class="line"><a name="l00315"></a><span class="lineno"> 315</span>  <span class="keywordflow">for</span> (t_index i=0; i<size; ++i) {</div><div class="line"><a name="l00316"></a><span class="lineno"> 316</span>  pred[i+1] = i;</div><div class="line"><a name="l00317"></a><span class="lineno"> 317</span>  succ[i] = i+1;</div><div class="line"><a name="l00318"></a><span class="lineno"> 318</span>  }</div><div class="line"><a name="l00319"></a><span class="lineno"> 319</span>  <span class="comment">// pred[0] is never accessed!</span></div><div class="line"><a name="l00320"></a><span class="lineno"> 320</span>  <span class="comment">//succ[size] is never accessed!</span></div><div class="line"><a name="l00321"></a><span class="lineno"> 321</span>  }</div><div class="line"><a name="l00322"></a><span class="lineno"> 322</span> </div><div class="line"><a name="l00323"></a><span class="lineno"> 323</span>  ~doubly_linked_list() {}</div><div class="line"><a name="l00324"></a><span class="lineno"> 324</span> </div><div class="line"><a name="l00325"></a><span class="lineno"> 325</span>  <span class="keywordtype">void</span> <span class="keyword">remove</span>(<span class="keyword">const</span> t_index idx) {</div><div class="line"><a name="l00326"></a><span class="lineno"> 326</span>  <span class="comment">// Remove an index from the list.</span></div><div class="line"><a name="l00327"></a><span class="lineno"> 327</span>  <span class="keywordflow">if</span> (idx==start) {</div><div class="line"><a name="l00328"></a><span class="lineno"> 328</span>  start = succ[idx];</div><div class="line"><a name="l00329"></a><span class="lineno"> 329</span>  }</div><div class="line"><a name="l00330"></a><span class="lineno"> 330</span>  <span class="keywordflow">else</span> {</div><div class="line"><a name="l00331"></a><span class="lineno"> 331</span>  succ[pred[idx]] = succ[idx];</div><div class="line"><a name="l00332"></a><span class="lineno"> 332</span>  pred[succ[idx]] = pred[idx];</div><div class="line"><a name="l00333"></a><span class="lineno"> 333</span>  }</div><div class="line"><a name="l00334"></a><span class="lineno"> 334</span>  succ[idx] = 0; <span class="comment">// Mark as inactive</span></div><div class="line"><a name="l00335"></a><span class="lineno"> 335</span>  }</div><div class="line"><a name="l00336"></a><span class="lineno"> 336</span> </div><div class="line"><a name="l00337"></a><span class="lineno"> 337</span>  <span class="keywordtype">bool</span> is_inactive(t_index idx)<span class="keyword"> const </span>{</div><div class="line"><a name="l00338"></a><span class="lineno"> 338</span>  <span class="keywordflow">return</span> (succ[idx]==0);</div><div class="line"><a name="l00339"></a><span class="lineno"> 339</span>  }</div><div class="line"><a name="l00340"></a><span class="lineno"> 340</span> };</div><div class="line"><a name="l00341"></a><span class="lineno"> 341</span> </div><div class="line"><a name="l00342"></a><span class="lineno"> 342</span> <span class="comment">// Indexing functions</span></div><div class="line"><a name="l00343"></a><span class="lineno"> 343</span> <span class="comment">// D is the upper triangular part of a symmetric (NxN)-matrix</span></div><div class="line"><a name="l00344"></a><span class="lineno"> 344</span> <span class="comment">// We require r_ < c_ !</span></div><div class="line"><a name="l00345"></a><span class="lineno"> 345</span> <span class="preprocessor">#define D_(r_,c_) ( D[(static_cast<std::ptrdiff_t>(2*N-3-(r_))*(r_)>>1)+(c_)-1] )</span></div><div class="line"><a name="l00346"></a><span class="lineno"> 346</span> <span class="comment">// Z is an ((N-1)x4)-array</span></div><div class="line"><a name="l00347"></a><span class="lineno"> 347</span> <span class="preprocessor">#define Z_(_r, _c) (Z[(_r)*4 + (_c)])</span></div><div class="line"><a name="l00348"></a><span class="lineno"> 348</span> </div><div class="line"><a name="l00349"></a><span class="lineno"> 349</span> <span class="comment">/*</span></div><div class="line"><a name="l00350"></a><span class="lineno"> 350</span> <span class="comment"> Lookup function for a union-find data structure.</span></div><div class="line"><a name="l00351"></a><span class="lineno"> 351</span> <span class="comment"></span></div><div class="line"><a name="l00352"></a><span class="lineno"> 352</span> <span class="comment"> The function finds the root of idx by going iteratively through all</span></div><div class="line"><a name="l00353"></a><span class="lineno"> 353</span> <span class="comment"> parent elements until a root is found. An element i is a root if</span></div><div class="line"><a name="l00354"></a><span class="lineno"> 354</span> <span class="comment"> nodes[i] is zero. To make subsequent searches faster, the entry for</span></div><div class="line"><a name="l00355"></a><span class="lineno"> 355</span> <span class="comment"> idx and all its parents is updated with the root element.</span></div><div class="line"><a name="l00356"></a><span class="lineno"> 356</span> <span class="comment"> */</span></div><div class="line"><a name="l00357"></a><span class="lineno"> 357</span> <span class="keyword">class </span>union_find {</div><div class="line"><a name="l00358"></a><span class="lineno"> 358</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00359"></a><span class="lineno"> 359</span>  auto_array_ptr<t_index> parent;</div><div class="line"><a name="l00360"></a><span class="lineno"> 360</span>  t_index nextparent;</div><div class="line"><a name="l00361"></a><span class="lineno"> 361</span> </div><div class="line"><a name="l00362"></a><span class="lineno"> 362</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00363"></a><span class="lineno"> 363</span>  union_find(<span class="keyword">const</span> t_index size)</div><div class="line"><a name="l00364"></a><span class="lineno"> 364</span>  : parent(size>0 ? 2*size-1 : 0, 0)</div><div class="line"><a name="l00365"></a><span class="lineno"> 365</span>  , nextparent(size)</div><div class="line"><a name="l00366"></a><span class="lineno"> 366</span>  { }</div><div class="line"><a name="l00367"></a><span class="lineno"> 367</span> </div><div class="line"><a name="l00368"></a><span class="lineno"> 368</span>  t_index Find (t_index idx)<span class="keyword"> const </span>{</div><div class="line"><a name="l00369"></a><span class="lineno"> 369</span>  <span class="keywordflow">if</span> (parent[idx] != 0 ) { <span class="comment">// a → b</span></div><div class="line"><a name="l00370"></a><span class="lineno"> 370</span>  t_index p = idx;</div><div class="line"><a name="l00371"></a><span class="lineno"> 371</span>  idx = parent[idx];</div><div class="line"><a name="l00372"></a><span class="lineno"> 372</span>  <span class="keywordflow">if</span> (parent[idx] != 0 ) { <span class="comment">// a → b → c</span></div><div class="line"><a name="l00373"></a><span class="lineno"> 373</span>  <span class="keywordflow">do</span> {</div><div class="line"><a name="l00374"></a><span class="lineno"> 374</span>  idx = parent[idx];</div><div class="line"><a name="l00375"></a><span class="lineno"> 375</span>  } <span class="keywordflow">while</span> (parent[idx] != 0);</div><div class="line"><a name="l00376"></a><span class="lineno"> 376</span>  <span class="keywordflow">do</span> {</div><div class="line"><a name="l00377"></a><span class="lineno"> 377</span>  t_index tmp = parent[p];</div><div class="line"><a name="l00378"></a><span class="lineno"> 378</span>  parent[p] = idx;</div><div class="line"><a name="l00379"></a><span class="lineno"> 379</span>  p = tmp;</div><div class="line"><a name="l00380"></a><span class="lineno"> 380</span>  } <span class="keywordflow">while</span> (parent[p] != idx);</div><div class="line"><a name="l00381"></a><span class="lineno"> 381</span>  }</div><div class="line"><a name="l00382"></a><span class="lineno"> 382</span>  }</div><div class="line"><a name="l00383"></a><span class="lineno"> 383</span>  <span class="keywordflow">return</span> idx;</div><div class="line"><a name="l00384"></a><span class="lineno"> 384</span>  }</div><div class="line"><a name="l00385"></a><span class="lineno"> 385</span> </div><div class="line"><a name="l00386"></a><span class="lineno"> 386</span>  <span class="keywordtype">void</span> Union (<span class="keyword">const</span> t_index node1, <span class="keyword">const</span> t_index node2) {</div><div class="line"><a name="l00387"></a><span class="lineno"> 387</span>  parent[node1] = parent[node2] = nextparent++;</div><div class="line"><a name="l00388"></a><span class="lineno"> 388</span>  }</div><div class="line"><a name="l00389"></a><span class="lineno"> 389</span> };</div><div class="line"><a name="l00390"></a><span class="lineno"> 390</span> </div><div class="line"><a name="l00391"></a><span class="lineno"> 391</span> <span class="keyword">class </span>nan_error{};</div><div class="line"><a name="l00392"></a><span class="lineno"> 392</span> <span class="preprocessor">#ifdef FE_INVALID</span></div><div class="line"><a name="l00393"></a><span class="lineno"> 393</span> <span class="keyword">class </span>fenv_error{};</div><div class="line"><a name="l00394"></a><span class="lineno"> 394</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00395"></a><span class="lineno"> 395</span> </div><div class="line"><a name="l00396"></a><span class="lineno"> 396</span> <span class="keyword">static</span> <span class="keywordtype">void</span> MST_linkage_core(<span class="keyword">const</span> t_index N, <span class="keyword">const</span> t_float * <span class="keyword">const</span> D,</div><div class="line"><a name="l00397"></a><span class="lineno"> 397</span>  cluster_result & Z2) {</div><div class="line"><a name="l00398"></a><span class="lineno"> 398</span> <span class="comment">/*</span></div><div class="line"><a name="l00399"></a><span class="lineno"> 399</span> <span class="comment"> N: integer, number of data points</span></div><div class="line"><a name="l00400"></a><span class="lineno"> 400</span> <span class="comment"> D: condensed distance matrix N*(N-1)/2</span></div><div class="line"><a name="l00401"></a><span class="lineno"> 401</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l00402"></a><span class="lineno"> 402</span> <span class="comment"></span></div><div class="line"><a name="l00403"></a><span class="lineno"> 403</span> <span class="comment"> The basis of this algorithm is an algorithm by Rohlf:</span></div><div class="line"><a name="l00404"></a><span class="lineno"> 404</span> <span class="comment"></span></div><div class="line"><a name="l00405"></a><span class="lineno"> 405</span> <span class="comment"> F. James Rohlf, Hierarchical clustering using the minimum spanning tree,</span></div><div class="line"><a name="l00406"></a><span class="lineno"> 406</span> <span class="comment"> The Computer Journal, vol. 16, 1973, p. 93–95.</span></div><div class="line"><a name="l00407"></a><span class="lineno"> 407</span> <span class="comment">*/</span></div><div class="line"><a name="l00408"></a><span class="lineno"> 408</span>  t_index i;</div><div class="line"><a name="l00409"></a><span class="lineno"> 409</span>  t_index idx2;</div><div class="line"><a name="l00410"></a><span class="lineno"> 410</span>  doubly_linked_list active_nodes(N);</div><div class="line"><a name="l00411"></a><span class="lineno"> 411</span>  auto_array_ptr<t_float> d(N);</div><div class="line"><a name="l00412"></a><span class="lineno"> 412</span> </div><div class="line"><a name="l00413"></a><span class="lineno"> 413</span>  t_index prev_node;</div><div class="line"><a name="l00414"></a><span class="lineno"> 414</span>  t_float min;</div><div class="line"><a name="l00415"></a><span class="lineno"> 415</span> </div><div class="line"><a name="l00416"></a><span class="lineno"> 416</span>  <span class="comment">// first iteration</span></div><div class="line"><a name="l00417"></a><span class="lineno"> 417</span>  idx2 = 1;</div><div class="line"><a name="l00418"></a><span class="lineno"> 418</span>  min = std::numeric_limits<t_float>::infinity();</div><div class="line"><a name="l00419"></a><span class="lineno"> 419</span>  <span class="keywordflow">for</span> (i=1; i<N; ++i) {</div><div class="line"><a name="l00420"></a><span class="lineno"> 420</span>  d[i] = D[i-1];</div><div class="line"><a name="l00421"></a><span class="lineno"> 421</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00422"></a><span class="lineno"> 422</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00423"></a><span class="lineno"> 423</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00424"></a><span class="lineno"> 424</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00425"></a><span class="lineno"> 425</span>  <span class="keywordflow">if</span> (d[i] < min) {</div><div class="line"><a name="l00426"></a><span class="lineno"> 426</span>  min = d[i];</div><div class="line"><a name="l00427"></a><span class="lineno"> 427</span>  idx2 = i;</div><div class="line"><a name="l00428"></a><span class="lineno"> 428</span>  }</div><div class="line"><a name="l00429"></a><span class="lineno"> 429</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(d[i]))</div><div class="line"><a name="l00430"></a><span class="lineno"> 430</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00431"></a><span class="lineno"> 431</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00432"></a><span class="lineno"> 432</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00433"></a><span class="lineno"> 433</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00434"></a><span class="lineno"> 434</span>  }</div><div class="line"><a name="l00435"></a><span class="lineno"> 435</span>  Z2.append(0, idx2, min);</div><div class="line"><a name="l00436"></a><span class="lineno"> 436</span> </div><div class="line"><a name="l00437"></a><span class="lineno"> 437</span>  <span class="keywordflow">for</span> (t_index j=1; j<N-1; ++j) {</div><div class="line"><a name="l00438"></a><span class="lineno"> 438</span>  prev_node = idx2;</div><div class="line"><a name="l00439"></a><span class="lineno"> 439</span>  active_nodes.remove(prev_node);</div><div class="line"><a name="l00440"></a><span class="lineno"> 440</span> </div><div class="line"><a name="l00441"></a><span class="lineno"> 441</span>  idx2 = active_nodes.succ[0];</div><div class="line"><a name="l00442"></a><span class="lineno"> 442</span>  min = d[idx2];</div><div class="line"><a name="l00443"></a><span class="lineno"> 443</span>  <span class="keywordflow">for</span> (i=idx2; i<prev_node; i=active_nodes.succ[i]) {</div><div class="line"><a name="l00444"></a><span class="lineno"> 444</span>  t_float tmp = D_(i, prev_node);</div><div class="line"><a name="l00445"></a><span class="lineno"> 445</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00446"></a><span class="lineno"> 446</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00447"></a><span class="lineno"> 447</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00448"></a><span class="lineno"> 448</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00449"></a><span class="lineno"> 449</span>  <span class="keywordflow">if</span> (tmp < d[i])</div><div class="line"><a name="l00450"></a><span class="lineno"> 450</span>  d[i] = tmp;</div><div class="line"><a name="l00451"></a><span class="lineno"> 451</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(tmp))</div><div class="line"><a name="l00452"></a><span class="lineno"> 452</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00453"></a><span class="lineno"> 453</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00454"></a><span class="lineno"> 454</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00455"></a><span class="lineno"> 455</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00456"></a><span class="lineno"> 456</span>  <span class="keywordflow">if</span> (d[i] < min) {</div><div class="line"><a name="l00457"></a><span class="lineno"> 457</span>  min = d[i];</div><div class="line"><a name="l00458"></a><span class="lineno"> 458</span>  idx2 = i;</div><div class="line"><a name="l00459"></a><span class="lineno"> 459</span>  }</div><div class="line"><a name="l00460"></a><span class="lineno"> 460</span>  }</div><div class="line"><a name="l00461"></a><span class="lineno"> 461</span>  <span class="keywordflow">for</span> (; i<N; i=active_nodes.succ[i]) {</div><div class="line"><a name="l00462"></a><span class="lineno"> 462</span>  t_float tmp = D_(prev_node, i);</div><div class="line"><a name="l00463"></a><span class="lineno"> 463</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00464"></a><span class="lineno"> 464</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00465"></a><span class="lineno"> 465</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00466"></a><span class="lineno"> 466</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00467"></a><span class="lineno"> 467</span>  <span class="keywordflow">if</span> (d[i] > tmp)</div><div class="line"><a name="l00468"></a><span class="lineno"> 468</span>  d[i] = tmp;</div><div class="line"><a name="l00469"></a><span class="lineno"> 469</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(tmp))</div><div class="line"><a name="l00470"></a><span class="lineno"> 470</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00471"></a><span class="lineno"> 471</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00472"></a><span class="lineno"> 472</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00473"></a><span class="lineno"> 473</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00474"></a><span class="lineno"> 474</span>  <span class="keywordflow">if</span> (d[i] < min) {</div><div class="line"><a name="l00475"></a><span class="lineno"> 475</span>  min = d[i];</div><div class="line"><a name="l00476"></a><span class="lineno"> 476</span>  idx2 = i;</div><div class="line"><a name="l00477"></a><span class="lineno"> 477</span>  }</div><div class="line"><a name="l00478"></a><span class="lineno"> 478</span>  }</div><div class="line"><a name="l00479"></a><span class="lineno"> 479</span>  Z2.append(prev_node, idx2, min);</div><div class="line"><a name="l00480"></a><span class="lineno"> 480</span>  }</div><div class="line"><a name="l00481"></a><span class="lineno"> 481</span> }</div><div class="line"><a name="l00482"></a><span class="lineno"> 482</span> </div><div class="line"><a name="l00483"></a><span class="lineno"> 483</span> <span class="comment">/* Functions for the update of the dissimilarity array */</span></div><div class="line"><a name="l00484"></a><span class="lineno"> 484</span> </div><div class="line"><a name="l00485"></a><span class="lineno"> 485</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_single( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a ) {</div><div class="line"><a name="l00486"></a><span class="lineno"> 486</span>  <span class="keywordflow">if</span> (*b > a) *b = a;</div><div class="line"><a name="l00487"></a><span class="lineno"> 487</span> }</div><div class="line"><a name="l00488"></a><span class="lineno"> 488</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_complete( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a ) {</div><div class="line"><a name="l00489"></a><span class="lineno"> 489</span>  <span class="keywordflow">if</span> (*b < a) *b = a;</div><div class="line"><a name="l00490"></a><span class="lineno"> 490</span> }</div><div class="line"><a name="l00491"></a><span class="lineno"> 491</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_average( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a, <span class="keyword">const</span> t_float s, <span class="keyword">const</span> t_float t) {</div><div class="line"><a name="l00492"></a><span class="lineno"> 492</span>  *b = s*a + t*(*b);</div><div class="line"><a name="l00493"></a><span class="lineno"> 493</span> <span class="preprocessor"> #ifndef FE_INVALID</span></div><div class="line"><a name="l00494"></a><span class="lineno"> 494</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00495"></a><span class="lineno"> 495</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00496"></a><span class="lineno"> 496</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00497"></a><span class="lineno"> 497</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00498"></a><span class="lineno"> 498</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*b)) {</div><div class="line"><a name="l00499"></a><span class="lineno"> 499</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00500"></a><span class="lineno"> 500</span>  }</div><div class="line"><a name="l00501"></a><span class="lineno"> 501</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00502"></a><span class="lineno"> 502</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00503"></a><span class="lineno"> 503</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00504"></a><span class="lineno"> 504</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00505"></a><span class="lineno"> 505</span> }</div><div class="line"><a name="l00506"></a><span class="lineno"> 506</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_weighted( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a) {</div><div class="line"><a name="l00507"></a><span class="lineno"> 507</span>  *b = (a+*b)*.5;</div><div class="line"><a name="l00508"></a><span class="lineno"> 508</span> <span class="preprocessor"> #ifndef FE_INVALID</span></div><div class="line"><a name="l00509"></a><span class="lineno"> 509</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00510"></a><span class="lineno"> 510</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00511"></a><span class="lineno"> 511</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00512"></a><span class="lineno"> 512</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00513"></a><span class="lineno"> 513</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*b)) {</div><div class="line"><a name="l00514"></a><span class="lineno"> 514</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00515"></a><span class="lineno"> 515</span>  }</div><div class="line"><a name="l00516"></a><span class="lineno"> 516</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00517"></a><span class="lineno"> 517</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00518"></a><span class="lineno"> 518</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00519"></a><span class="lineno"> 519</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00520"></a><span class="lineno"> 520</span> }</div><div class="line"><a name="l00521"></a><span class="lineno"> 521</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_ward( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a, <span class="keyword">const</span> t_float c, <span class="keyword">const</span> t_float s, <span class="keyword">const</span> t_float t, <span class="keyword">const</span> t_float v) {</div><div class="line"><a name="l00522"></a><span class="lineno"> 522</span>  *b = ( (v+s)*a - v*c + (v+t)*(*b) ) / (s+t+v);</div><div class="line"><a name="l00523"></a><span class="lineno"> 523</span>  <span class="comment">//*b = a+(*b)-(t*a+s*(*b)+v*c)/(s+t+v);</span></div><div class="line"><a name="l00524"></a><span class="lineno"> 524</span> <span class="preprocessor"> #ifndef FE_INVALID</span></div><div class="line"><a name="l00525"></a><span class="lineno"> 525</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00526"></a><span class="lineno"> 526</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00527"></a><span class="lineno"> 527</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00528"></a><span class="lineno"> 528</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00529"></a><span class="lineno"> 529</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*b)) {</div><div class="line"><a name="l00530"></a><span class="lineno"> 530</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00531"></a><span class="lineno"> 531</span>  }</div><div class="line"><a name="l00532"></a><span class="lineno"> 532</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00533"></a><span class="lineno"> 533</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00534"></a><span class="lineno"> 534</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00535"></a><span class="lineno"> 535</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00536"></a><span class="lineno"> 536</span> }</div><div class="line"><a name="l00537"></a><span class="lineno"> 537</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_centroid( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a, <span class="keyword">const</span> t_float stc, <span class="keyword">const</span> t_float s, <span class="keyword">const</span> t_float t) {</div><div class="line"><a name="l00538"></a><span class="lineno"> 538</span>  *b = s*a - stc + t*(*b);</div><div class="line"><a name="l00539"></a><span class="lineno"> 539</span> <span class="preprocessor"> #ifndef FE_INVALID</span></div><div class="line"><a name="l00540"></a><span class="lineno"> 540</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*b)) {</div><div class="line"><a name="l00541"></a><span class="lineno"> 541</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00542"></a><span class="lineno"> 542</span>  }</div><div class="line"><a name="l00543"></a><span class="lineno"> 543</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00544"></a><span class="lineno"> 544</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00545"></a><span class="lineno"> 545</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00546"></a><span class="lineno"> 546</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00547"></a><span class="lineno"> 547</span> }</div><div class="line"><a name="l00548"></a><span class="lineno"> 548</span> <span class="keyword">inline</span> <span class="keyword">static</span> <span class="keywordtype">void</span> f_median( t_float * <span class="keyword">const</span> b, <span class="keyword">const</span> t_float a, <span class="keyword">const</span> t_float c_4) {</div><div class="line"><a name="l00549"></a><span class="lineno"> 549</span>  *b = (a+(*b))*.5 - c_4;</div><div class="line"><a name="l00550"></a><span class="lineno"> 550</span> <span class="preprocessor"> #ifndef FE_INVALID</span></div><div class="line"><a name="l00551"></a><span class="lineno"> 551</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00552"></a><span class="lineno"> 552</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00553"></a><span class="lineno"> 553</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00554"></a><span class="lineno"> 554</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00555"></a><span class="lineno"> 555</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*b)) {</div><div class="line"><a name="l00556"></a><span class="lineno"> 556</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00557"></a><span class="lineno"> 557</span>  }</div><div class="line"><a name="l00558"></a><span class="lineno"> 558</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00559"></a><span class="lineno"> 559</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00560"></a><span class="lineno"> 560</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00561"></a><span class="lineno"> 561</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00562"></a><span class="lineno"> 562</span> }</div><div class="line"><a name="l00563"></a><span class="lineno"> 563</span> </div><div class="line"><a name="l00564"></a><span class="lineno"> 564</span> <span class="keyword">template</span> <method_codes method, <span class="keyword">typename</span> t_members></div><div class="line"><a name="l00565"></a><span class="lineno"> 565</span> <span class="keyword">static</span> <span class="keywordtype">void</span> NN_chain_core(<span class="keyword">const</span> t_index N, t_float * <span class="keyword">const</span> D, t_members * <span class="keyword">const</span> members, cluster_result & Z2) {</div><div class="line"><a name="l00566"></a><span class="lineno"> 566</span> <span class="comment">/*</span></div><div class="line"><a name="l00567"></a><span class="lineno"> 567</span> <span class="comment"> N: integer</span></div><div class="line"><a name="l00568"></a><span class="lineno"> 568</span> <span class="comment"> D: condensed distance matrix N*(N-1)/2</span></div><div class="line"><a name="l00569"></a><span class="lineno"> 569</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l00570"></a><span class="lineno"> 570</span> <span class="comment"></span></div><div class="line"><a name="l00571"></a><span class="lineno"> 571</span> <span class="comment"> This is the NN-chain algorithm, described on page 86 in the following book:</span></div><div class="line"><a name="l00572"></a><span class="lineno"> 572</span> <span class="comment"></span></div><div class="line"><a name="l00573"></a><span class="lineno"> 573</span> <span class="comment"> Fionn Murtagh, Multidimensional Clustering Algorithms,</span></div><div class="line"><a name="l00574"></a><span class="lineno"> 574</span> <span class="comment"> Vienna, Würzburg: Physica-Verlag, 1985.</span></div><div class="line"><a name="l00575"></a><span class="lineno"> 575</span> <span class="comment">*/</span></div><div class="line"><a name="l00576"></a><span class="lineno"> 576</span>  t_index i;</div><div class="line"><a name="l00577"></a><span class="lineno"> 577</span> </div><div class="line"><a name="l00578"></a><span class="lineno"> 578</span>  auto_array_ptr<t_index> NN_chain(N);</div><div class="line"><a name="l00579"></a><span class="lineno"> 579</span>  t_index NN_chain_tip = 0;</div><div class="line"><a name="l00580"></a><span class="lineno"> 580</span> </div><div class="line"><a name="l00581"></a><span class="lineno"> 581</span>  t_index idx1, idx2;</div><div class="line"><a name="l00582"></a><span class="lineno"> 582</span> </div><div class="line"><a name="l00583"></a><span class="lineno"> 583</span>  t_float size1, size2;</div><div class="line"><a name="l00584"></a><span class="lineno"> 584</span>  doubly_linked_list active_nodes(N);</div><div class="line"><a name="l00585"></a><span class="lineno"> 585</span> </div><div class="line"><a name="l00586"></a><span class="lineno"> 586</span>  t_float min;</div><div class="line"><a name="l00587"></a><span class="lineno"> 587</span> </div><div class="line"><a name="l00588"></a><span class="lineno"> 588</span>  <span class="keywordflow">for</span> (t_float <span class="keyword">const</span> * DD=D; DD!=D+(<span class="keyword">static_cast<</span>std::ptrdiff_t<span class="keyword">></span>(N)*(N-1)>>1);</div><div class="line"><a name="l00589"></a><span class="lineno"> 589</span>  ++DD) {</div><div class="line"><a name="l00590"></a><span class="lineno"> 590</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00591"></a><span class="lineno"> 591</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00592"></a><span class="lineno"> 592</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00593"></a><span class="lineno"> 593</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00594"></a><span class="lineno"> 594</span>  <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*DD)) {</div><div class="line"><a name="l00595"></a><span class="lineno"> 595</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00596"></a><span class="lineno"> 596</span>  }</div><div class="line"><a name="l00597"></a><span class="lineno"> 597</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00598"></a><span class="lineno"> 598</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00599"></a><span class="lineno"> 599</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00600"></a><span class="lineno"> 600</span>  }</div><div class="line"><a name="l00601"></a><span class="lineno"> 601</span> </div><div class="line"><a name="l00602"></a><span class="lineno"> 602</span> <span class="preprocessor"> #ifdef FE_INVALID</span></div><div class="line"><a name="l00603"></a><span class="lineno"> 603</span>  <span class="keywordflow">if</span> (feclearexcept(FE_INVALID)) <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: fenv error"</span>);</div><div class="line"><a name="l00604"></a><span class="lineno"> 604</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00605"></a><span class="lineno"> 605</span> </div><div class="line"><a name="l00606"></a><span class="lineno"> 606</span>  <span class="keywordflow">for</span> (t_index j=0; j<N-1; ++j) {</div><div class="line"><a name="l00607"></a><span class="lineno"> 607</span>  <span class="keywordflow">if</span> (NN_chain_tip <= 3) {</div><div class="line"><a name="l00608"></a><span class="lineno"> 608</span>  NN_chain[0] = idx1 = active_nodes.start;</div><div class="line"><a name="l00609"></a><span class="lineno"> 609</span>  NN_chain_tip = 1;</div><div class="line"><a name="l00610"></a><span class="lineno"> 610</span> </div><div class="line"><a name="l00611"></a><span class="lineno"> 611</span>  idx2 = active_nodes.succ[idx1];</div><div class="line"><a name="l00612"></a><span class="lineno"> 612</span>  min = D_(idx1,idx2);</div><div class="line"><a name="l00613"></a><span class="lineno"> 613</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i]) {</div><div class="line"><a name="l00614"></a><span class="lineno"> 614</span>  <span class="keywordflow">if</span> (D_(idx1,i) < min) {</div><div class="line"><a name="l00615"></a><span class="lineno"> 615</span>  min = D_(idx1,i);</div><div class="line"><a name="l00616"></a><span class="lineno"> 616</span>  idx2 = i;</div><div class="line"><a name="l00617"></a><span class="lineno"> 617</span>  }</div><div class="line"><a name="l00618"></a><span class="lineno"> 618</span>  }</div><div class="line"><a name="l00619"></a><span class="lineno"> 619</span>  } <span class="comment">// a: idx1 b: idx2</span></div><div class="line"><a name="l00620"></a><span class="lineno"> 620</span>  <span class="keywordflow">else</span> {</div><div class="line"><a name="l00621"></a><span class="lineno"> 621</span>  NN_chain_tip -= 3;</div><div class="line"><a name="l00622"></a><span class="lineno"> 622</span>  idx1 = NN_chain[NN_chain_tip-1];</div><div class="line"><a name="l00623"></a><span class="lineno"> 623</span>  idx2 = NN_chain[NN_chain_tip];</div><div class="line"><a name="l00624"></a><span class="lineno"> 624</span>  min = idx1<idx2 ? D_(idx1,idx2) : D_(idx2,idx1);</div><div class="line"><a name="l00625"></a><span class="lineno"> 625</span>  } <span class="comment">// a: idx1 b: idx2</span></div><div class="line"><a name="l00626"></a><span class="lineno"> 626</span> </div><div class="line"><a name="l00627"></a><span class="lineno"> 627</span>  <span class="keywordflow">do</span> {</div><div class="line"><a name="l00628"></a><span class="lineno"> 628</span>  NN_chain[NN_chain_tip] = idx2;</div><div class="line"><a name="l00629"></a><span class="lineno"> 629</span> </div><div class="line"><a name="l00630"></a><span class="lineno"> 630</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx2; i=active_nodes.succ[i]) {</div><div class="line"><a name="l00631"></a><span class="lineno"> 631</span>  <span class="keywordflow">if</span> (D_(i,idx2) < min) {</div><div class="line"><a name="l00632"></a><span class="lineno"> 632</span>  min = D_(i,idx2);</div><div class="line"><a name="l00633"></a><span class="lineno"> 633</span>  idx1 = i;</div><div class="line"><a name="l00634"></a><span class="lineno"> 634</span>  }</div><div class="line"><a name="l00635"></a><span class="lineno"> 635</span>  }</div><div class="line"><a name="l00636"></a><span class="lineno"> 636</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i]) {</div><div class="line"><a name="l00637"></a><span class="lineno"> 637</span>  <span class="keywordflow">if</span> (D_(idx2,i) < min) {</div><div class="line"><a name="l00638"></a><span class="lineno"> 638</span>  min = D_(idx2,i);</div><div class="line"><a name="l00639"></a><span class="lineno"> 639</span>  idx1 = i;</div><div class="line"><a name="l00640"></a><span class="lineno"> 640</span>  }</div><div class="line"><a name="l00641"></a><span class="lineno"> 641</span>  }</div><div class="line"><a name="l00642"></a><span class="lineno"> 642</span> </div><div class="line"><a name="l00643"></a><span class="lineno"> 643</span>  idx2 = idx1;</div><div class="line"><a name="l00644"></a><span class="lineno"> 644</span>  idx1 = NN_chain[NN_chain_tip++];</div><div class="line"><a name="l00645"></a><span class="lineno"> 645</span> </div><div class="line"><a name="l00646"></a><span class="lineno"> 646</span>  } <span class="keywordflow">while</span> (idx2 != NN_chain[NN_chain_tip-2]);</div><div class="line"><a name="l00647"></a><span class="lineno"> 647</span> </div><div class="line"><a name="l00648"></a><span class="lineno"> 648</span>  Z2.append(idx1, idx2, min);</div><div class="line"><a name="l00649"></a><span class="lineno"> 649</span> </div><div class="line"><a name="l00650"></a><span class="lineno"> 650</span>  <span class="keywordflow">if</span> (idx1>idx2) {</div><div class="line"><a name="l00651"></a><span class="lineno"> 651</span>  t_index tmp = idx1;</div><div class="line"><a name="l00652"></a><span class="lineno"> 652</span>  idx1 = idx2;</div><div class="line"><a name="l00653"></a><span class="lineno"> 653</span>  idx2 = tmp;</div><div class="line"><a name="l00654"></a><span class="lineno"> 654</span>  }</div><div class="line"><a name="l00655"></a><span class="lineno"> 655</span> </div><div class="line"><a name="l00656"></a><span class="lineno"> 656</span>  <span class="keywordflow">if</span> (method==METHOD_METR_AVERAGE ||</div><div class="line"><a name="l00657"></a><span class="lineno"> 657</span>  method==METHOD_METR_WARD) {</div><div class="line"><a name="l00658"></a><span class="lineno"> 658</span>  size1 = <span class="keyword">static_cast<</span>t_float<span class="keyword">></span>(members[idx1]);</div><div class="line"><a name="l00659"></a><span class="lineno"> 659</span>  size2 = <span class="keyword">static_cast<</span>t_float<span class="keyword">></span>(members[idx2]);</div><div class="line"><a name="l00660"></a><span class="lineno"> 660</span>  members[idx2] += members[idx1];</div><div class="line"><a name="l00661"></a><span class="lineno"> 661</span>  }</div><div class="line"><a name="l00662"></a><span class="lineno"> 662</span> </div><div class="line"><a name="l00663"></a><span class="lineno"> 663</span>  <span class="comment">// Remove the smaller index from the valid indices (active_nodes).</span></div><div class="line"><a name="l00664"></a><span class="lineno"> 664</span>  active_nodes.remove(idx1);</div><div class="line"><a name="l00665"></a><span class="lineno"> 665</span> </div><div class="line"><a name="l00666"></a><span class="lineno"> 666</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l00667"></a><span class="lineno"> 667</span>  <span class="keywordflow">case</span> METHOD_METR_SINGLE:</div><div class="line"><a name="l00668"></a><span class="lineno"> 668</span>  <span class="comment">/*</span></div><div class="line"><a name="l00669"></a><span class="lineno"> 669</span> <span class="comment"> Single linkage.</span></div><div class="line"><a name="l00670"></a><span class="lineno"> 670</span> <span class="comment"></span></div><div class="line"><a name="l00671"></a><span class="lineno"> 671</span> <span class="comment"> Characteristic: new distances are never longer than the old distances.</span></div><div class="line"><a name="l00672"></a><span class="lineno"> 672</span> <span class="comment"> */</span></div><div class="line"><a name="l00673"></a><span class="lineno"> 673</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l00674"></a><span class="lineno"> 674</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx1; i=active_nodes.succ[i])</div><div class="line"><a name="l00675"></a><span class="lineno"> 675</span>  f_single(&D_(i, idx2), D_(i, idx1) );</div><div class="line"><a name="l00676"></a><span class="lineno"> 676</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l00677"></a><span class="lineno"> 677</span>  <span class="keywordflow">for</span> (; i<idx2; i=active_nodes.succ[i])</div><div class="line"><a name="l00678"></a><span class="lineno"> 678</span>  f_single(&D_(i, idx2), D_(idx1, i) );</div><div class="line"><a name="l00679"></a><span class="lineno"> 679</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l00680"></a><span class="lineno"> 680</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i])</div><div class="line"><a name="l00681"></a><span class="lineno"> 681</span>  f_single(&D_(idx2, i), D_(idx1, i) );</div><div class="line"><a name="l00682"></a><span class="lineno"> 682</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l00683"></a><span class="lineno"> 683</span> </div><div class="line"><a name="l00684"></a><span class="lineno"> 684</span>  <span class="keywordflow">case</span> METHOD_METR_COMPLETE:</div><div class="line"><a name="l00685"></a><span class="lineno"> 685</span>  <span class="comment">/*</span></div><div class="line"><a name="l00686"></a><span class="lineno"> 686</span> <span class="comment"> Complete linkage.</span></div><div class="line"><a name="l00687"></a><span class="lineno"> 687</span> <span class="comment"></span></div><div class="line"><a name="l00688"></a><span class="lineno"> 688</span> <span class="comment"> Characteristic: new distances are never shorter than the old distances.</span></div><div class="line"><a name="l00689"></a><span class="lineno"> 689</span> <span class="comment"> */</span></div><div class="line"><a name="l00690"></a><span class="lineno"> 690</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l00691"></a><span class="lineno"> 691</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx1; i=active_nodes.succ[i])</div><div class="line"><a name="l00692"></a><span class="lineno"> 692</span>  f_complete(&D_(i, idx2), D_(i, idx1) );</div><div class="line"><a name="l00693"></a><span class="lineno"> 693</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l00694"></a><span class="lineno"> 694</span>  <span class="keywordflow">for</span> (; i<idx2; i=active_nodes.succ[i])</div><div class="line"><a name="l00695"></a><span class="lineno"> 695</span>  f_complete(&D_(i, idx2), D_(idx1, i) );</div><div class="line"><a name="l00696"></a><span class="lineno"> 696</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l00697"></a><span class="lineno"> 697</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i])</div><div class="line"><a name="l00698"></a><span class="lineno"> 698</span>  f_complete(&D_(idx2, i), D_(idx1, i) );</div><div class="line"><a name="l00699"></a><span class="lineno"> 699</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l00700"></a><span class="lineno"> 700</span> </div><div class="line"><a name="l00701"></a><span class="lineno"> 701</span>  <span class="keywordflow">case</span> METHOD_METR_AVERAGE: {</div><div class="line"><a name="l00702"></a><span class="lineno"> 702</span>  <span class="comment">/*</span></div><div class="line"><a name="l00703"></a><span class="lineno"> 703</span> <span class="comment"> Average linkage.</span></div><div class="line"><a name="l00704"></a><span class="lineno"> 704</span> <span class="comment"></span></div><div class="line"><a name="l00705"></a><span class="lineno"> 705</span> <span class="comment"> Shorter and longer distances can occur.</span></div><div class="line"><a name="l00706"></a><span class="lineno"> 706</span> <span class="comment"> */</span></div><div class="line"><a name="l00707"></a><span class="lineno"> 707</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l00708"></a><span class="lineno"> 708</span>  t_float s = size1/(size1+size2);</div><div class="line"><a name="l00709"></a><span class="lineno"> 709</span>  t_float t = size2/(size1+size2);</div><div class="line"><a name="l00710"></a><span class="lineno"> 710</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx1; i=active_nodes.succ[i])</div><div class="line"><a name="l00711"></a><span class="lineno"> 711</span>  f_average(&D_(i, idx2), D_(i, idx1), s, t );</div><div class="line"><a name="l00712"></a><span class="lineno"> 712</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l00713"></a><span class="lineno"> 713</span>  <span class="keywordflow">for</span> (; i<idx2; i=active_nodes.succ[i])</div><div class="line"><a name="l00714"></a><span class="lineno"> 714</span>  f_average(&D_(i, idx2), D_(idx1, i), s, t );</div><div class="line"><a name="l00715"></a><span class="lineno"> 715</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l00716"></a><span class="lineno"> 716</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i])</div><div class="line"><a name="l00717"></a><span class="lineno"> 717</span>  f_average(&D_(idx2, i), D_(idx1, i), s, t );</div><div class="line"><a name="l00718"></a><span class="lineno"> 718</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l00719"></a><span class="lineno"> 719</span>  }</div><div class="line"><a name="l00720"></a><span class="lineno"> 720</span> </div><div class="line"><a name="l00721"></a><span class="lineno"> 721</span>  <span class="keywordflow">case</span> METHOD_METR_WEIGHTED:</div><div class="line"><a name="l00722"></a><span class="lineno"> 722</span>  <span class="comment">/*</span></div><div class="line"><a name="l00723"></a><span class="lineno"> 723</span> <span class="comment"> Weighted linkage.</span></div><div class="line"><a name="l00724"></a><span class="lineno"> 724</span> <span class="comment"></span></div><div class="line"><a name="l00725"></a><span class="lineno"> 725</span> <span class="comment"> Shorter and longer distances can occur.</span></div><div class="line"><a name="l00726"></a><span class="lineno"> 726</span> <span class="comment"> */</span></div><div class="line"><a name="l00727"></a><span class="lineno"> 727</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l00728"></a><span class="lineno"> 728</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx1; i=active_nodes.succ[i])</div><div class="line"><a name="l00729"></a><span class="lineno"> 729</span>  f_weighted(&D_(i, idx2), D_(i, idx1) );</div><div class="line"><a name="l00730"></a><span class="lineno"> 730</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l00731"></a><span class="lineno"> 731</span>  <span class="keywordflow">for</span> (; i<idx2; i=active_nodes.succ[i])</div><div class="line"><a name="l00732"></a><span class="lineno"> 732</span>  f_weighted(&D_(i, idx2), D_(idx1, i) );</div><div class="line"><a name="l00733"></a><span class="lineno"> 733</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l00734"></a><span class="lineno"> 734</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i])</div><div class="line"><a name="l00735"></a><span class="lineno"> 735</span>  f_weighted(&D_(idx2, i), D_(idx1, i) );</div><div class="line"><a name="l00736"></a><span class="lineno"> 736</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l00737"></a><span class="lineno"> 737</span> </div><div class="line"><a name="l00738"></a><span class="lineno"> 738</span>  <span class="keywordflow">case</span> METHOD_METR_WARD:</div><div class="line"><a name="l00739"></a><span class="lineno"> 739</span>  <span class="comment">/*</span></div><div class="line"><a name="l00740"></a><span class="lineno"> 740</span> <span class="comment"> Ward linkage.</span></div><div class="line"><a name="l00741"></a><span class="lineno"> 741</span> <span class="comment"></span></div><div class="line"><a name="l00742"></a><span class="lineno"> 742</span> <span class="comment"> Shorter and longer distances can occur, not smaller than min(d1,d2)</span></div><div class="line"><a name="l00743"></a><span class="lineno"> 743</span> <span class="comment"> but maybe bigger than max(d1,d2).</span></div><div class="line"><a name="l00744"></a><span class="lineno"> 744</span> <span class="comment"> */</span></div><div class="line"><a name="l00745"></a><span class="lineno"> 745</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l00746"></a><span class="lineno"> 746</span>  <span class="comment">//t_float v = static_cast<t_float>(members[i]);</span></div><div class="line"><a name="l00747"></a><span class="lineno"> 747</span>  <span class="keywordflow">for</span> (i=active_nodes.start; i<idx1; i=active_nodes.succ[i])</div><div class="line"><a name="l00748"></a><span class="lineno"> 748</span>  f_ward(&D_(i, idx2), D_(i, idx1), min,</div><div class="line"><a name="l00749"></a><span class="lineno"> 749</span>  size1, size2, static_cast<t_float>(members[i]) );</div><div class="line"><a name="l00750"></a><span class="lineno"> 750</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l00751"></a><span class="lineno"> 751</span>  <span class="keywordflow">for</span> (; i<idx2; i=active_nodes.succ[i])</div><div class="line"><a name="l00752"></a><span class="lineno"> 752</span>  f_ward(&D_(i, idx2), D_(idx1, i), min,</div><div class="line"><a name="l00753"></a><span class="lineno"> 753</span>  size1, size2, static_cast<t_float>(members[i]) );</div><div class="line"><a name="l00754"></a><span class="lineno"> 754</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l00755"></a><span class="lineno"> 755</span>  <span class="keywordflow">for</span> (i=active_nodes.succ[idx2]; i<N; i=active_nodes.succ[i])</div><div class="line"><a name="l00756"></a><span class="lineno"> 756</span>  f_ward(&D_(idx2, i), D_(idx1, i), min,</div><div class="line"><a name="l00757"></a><span class="lineno"> 757</span>  size1, size2, static_cast<t_float>(members[i]) );</div><div class="line"><a name="l00758"></a><span class="lineno"> 758</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l00759"></a><span class="lineno"> 759</span> </div><div class="line"><a name="l00760"></a><span class="lineno"> 760</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l00761"></a><span class="lineno"> 761</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: invalid method"</span>);</div><div class="line"><a name="l00762"></a><span class="lineno"> 762</span>  }</div><div class="line"><a name="l00763"></a><span class="lineno"> 763</span>  }</div><div class="line"><a name="l00764"></a><span class="lineno"> 764</span> <span class="preprocessor"> #ifdef FE_INVALID</span></div><div class="line"><a name="l00765"></a><span class="lineno"> 765</span>  <span class="keywordflow">if</span> (fetestexcept(FE_INVALID)) <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: fenv error"</span>);</div><div class="line"><a name="l00766"></a><span class="lineno"> 766</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00767"></a><span class="lineno"> 767</span> }</div><div class="line"><a name="l00768"></a><span class="lineno"> 768</span> </div><div class="line"><a name="l00769"></a><span class="lineno"> 769</span> <span class="keyword">class </span>binary_min_heap {</div><div class="line"><a name="l00770"></a><span class="lineno"> 770</span>  <span class="comment">/*</span></div><div class="line"><a name="l00771"></a><span class="lineno"> 771</span> <span class="comment"> Class for a binary min-heap. The data resides in an array A. The elements of</span></div><div class="line"><a name="l00772"></a><span class="lineno"> 772</span> <span class="comment"> A are not changed but two lists I and R of indices are generated which point</span></div><div class="line"><a name="l00773"></a><span class="lineno"> 773</span> <span class="comment"> to elements of A and backwards.</span></div><div class="line"><a name="l00774"></a><span class="lineno"> 774</span> <span class="comment"></span></div><div class="line"><a name="l00775"></a><span class="lineno"> 775</span> <span class="comment"> The heap tree structure is</span></div><div class="line"><a name="l00776"></a><span class="lineno"> 776</span> <span class="comment"></span></div><div class="line"><a name="l00777"></a><span class="lineno"> 777</span> <span class="comment"> H[2*i+1] H[2*i+2]</span></div><div class="line"><a name="l00778"></a><span class="lineno"> 778</span> <span class="comment"> \ /</span></div><div class="line"><a name="l00779"></a><span class="lineno"> 779</span> <span class="comment"> \ /</span></div><div class="line"><a name="l00780"></a><span class="lineno"> 780</span> <span class="comment"> ≤ ≤</span></div><div class="line"><a name="l00781"></a><span class="lineno"> 781</span> <span class="comment"> \ /</span></div><div class="line"><a name="l00782"></a><span class="lineno"> 782</span> <span class="comment"> \ /</span></div><div class="line"><a name="l00783"></a><span class="lineno"> 783</span> <span class="comment"> H[i]</span></div><div class="line"><a name="l00784"></a><span class="lineno"> 784</span> <span class="comment"></span></div><div class="line"><a name="l00785"></a><span class="lineno"> 785</span> <span class="comment"> where the children must be less or equal than their parent. Thus, H[0]</span></div><div class="line"><a name="l00786"></a><span class="lineno"> 786</span> <span class="comment"> contains the minimum. The lists I and R are made such that H[i] = A[I[i]]</span></div><div class="line"><a name="l00787"></a><span class="lineno"> 787</span> <span class="comment"> and R[I[i]] = i.</span></div><div class="line"><a name="l00788"></a><span class="lineno"> 788</span> <span class="comment"></span></div><div class="line"><a name="l00789"></a><span class="lineno"> 789</span> <span class="comment"> This implementation is not designed to handle NaN values.</span></div><div class="line"><a name="l00790"></a><span class="lineno"> 790</span> <span class="comment"> */</span></div><div class="line"><a name="l00791"></a><span class="lineno"> 791</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00792"></a><span class="lineno"> 792</span>  t_float * <span class="keyword">const</span> A;</div><div class="line"><a name="l00793"></a><span class="lineno"> 793</span>  t_index size;</div><div class="line"><a name="l00794"></a><span class="lineno"> 794</span>  auto_array_ptr<t_index> I;</div><div class="line"><a name="l00795"></a><span class="lineno"> 795</span>  auto_array_ptr<t_index> R;</div><div class="line"><a name="l00796"></a><span class="lineno"> 796</span> </div><div class="line"><a name="l00797"></a><span class="lineno"> 797</span>  <span class="comment">// no default constructor</span></div><div class="line"><a name="l00798"></a><span class="lineno"> 798</span>  binary_min_heap();</div><div class="line"><a name="l00799"></a><span class="lineno"> 799</span>  <span class="comment">// noncopyable</span></div><div class="line"><a name="l00800"></a><span class="lineno"> 800</span>  binary_min_heap(binary_min_heap <span class="keyword">const</span> &);</div><div class="line"><a name="l00801"></a><span class="lineno"> 801</span>  binary_min_heap & operator=(binary_min_heap <span class="keyword">const</span> &);</div><div class="line"><a name="l00802"></a><span class="lineno"> 802</span> </div><div class="line"><a name="l00803"></a><span class="lineno"> 803</span> <span class="keyword">public</span>:</div><div class="line"><a name="l00804"></a><span class="lineno"> 804</span>  binary_min_heap(t_float * <span class="keyword">const</span> A_, <span class="keyword">const</span> t_index size_)</div><div class="line"><a name="l00805"></a><span class="lineno"> 805</span>  : A(A_), size(size_), I(size), R(size)</div><div class="line"><a name="l00806"></a><span class="lineno"> 806</span>  { <span class="comment">// Allocate memory and initialize the lists I and R to the identity. This</span></div><div class="line"><a name="l00807"></a><span class="lineno"> 807</span>  <span class="comment">// does not make it a heap. Call heapify afterwards!</span></div><div class="line"><a name="l00808"></a><span class="lineno"> 808</span>  <span class="keywordflow">for</span> (t_index i=0; i<size; ++i)</div><div class="line"><a name="l00809"></a><span class="lineno"> 809</span>  R[i] = I[i] = i;</div><div class="line"><a name="l00810"></a><span class="lineno"> 810</span>  }</div><div class="line"><a name="l00811"></a><span class="lineno"> 811</span> </div><div class="line"><a name="l00812"></a><span class="lineno"> 812</span>  binary_min_heap(t_float * <span class="keyword">const</span> A_, <span class="keyword">const</span> t_index size1, <span class="keyword">const</span> t_index size2,</div><div class="line"><a name="l00813"></a><span class="lineno"> 813</span>  <span class="keyword">const</span> t_index start)</div><div class="line"><a name="l00814"></a><span class="lineno"> 814</span>  : A(A_), size(size1), I(size1), R(size2)</div><div class="line"><a name="l00815"></a><span class="lineno"> 815</span>  { <span class="comment">// Allocate memory and initialize the lists I and R to the identity. This</span></div><div class="line"><a name="l00816"></a><span class="lineno"> 816</span>  <span class="comment">// does not make it a heap. Call heapify afterwards!</span></div><div class="line"><a name="l00817"></a><span class="lineno"> 817</span>  <span class="keywordflow">for</span> (t_index i=0; i<size; ++i) {</div><div class="line"><a name="l00818"></a><span class="lineno"> 818</span>  R[i+start] = i;</div><div class="line"><a name="l00819"></a><span class="lineno"> 819</span>  I[i] = i + start;</div><div class="line"><a name="l00820"></a><span class="lineno"> 820</span>  }</div><div class="line"><a name="l00821"></a><span class="lineno"> 821</span>  }</div><div class="line"><a name="l00822"></a><span class="lineno"> 822</span> </div><div class="line"><a name="l00823"></a><span class="lineno"> 823</span>  ~binary_min_heap() {}</div><div class="line"><a name="l00824"></a><span class="lineno"> 824</span> </div><div class="line"><a name="l00825"></a><span class="lineno"> 825</span>  <span class="keywordtype">void</span> heapify() {</div><div class="line"><a name="l00826"></a><span class="lineno"> 826</span>  <span class="comment">// Arrange the indices I and R so that H[i] := A[I[i]] satisfies the heap</span></div><div class="line"><a name="l00827"></a><span class="lineno"> 827</span>  <span class="comment">// condition H[i] < H[2*i+1] and H[i] < H[2*i+2] for each i.</span></div><div class="line"><a name="l00828"></a><span class="lineno"> 828</span>  <span class="comment">//</span></div><div class="line"><a name="l00829"></a><span class="lineno"> 829</span>  <span class="comment">// Complexity: Θ(size)</span></div><div class="line"><a name="l00830"></a><span class="lineno"> 830</span>  <span class="comment">// Reference: Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms,</span></div><div class="line"><a name="l00831"></a><span class="lineno"> 831</span>  <span class="comment">// 3rd ed., 2009, Section 6.3 “Building a heap”</span></div><div class="line"><a name="l00832"></a><span class="lineno"> 832</span>  t_index idx;</div><div class="line"><a name="l00833"></a><span class="lineno"> 833</span>  <span class="keywordflow">for</span> (idx=(size>>1); idx>0; ) {</div><div class="line"><a name="l00834"></a><span class="lineno"> 834</span>  --idx;</div><div class="line"><a name="l00835"></a><span class="lineno"> 835</span>  update_geq_(idx);</div><div class="line"><a name="l00836"></a><span class="lineno"> 836</span>  }</div><div class="line"><a name="l00837"></a><span class="lineno"> 837</span>  }</div><div class="line"><a name="l00838"></a><span class="lineno"> 838</span> </div><div class="line"><a name="l00839"></a><span class="lineno"> 839</span>  <span class="keyword">inline</span> t_index argmin()<span class="keyword"> const </span>{</div><div class="line"><a name="l00840"></a><span class="lineno"> 840</span>  <span class="comment">// Return the minimal element.</span></div><div class="line"><a name="l00841"></a><span class="lineno"> 841</span>  <span class="keywordflow">return</span> I[0];</div><div class="line"><a name="l00842"></a><span class="lineno"> 842</span>  }</div><div class="line"><a name="l00843"></a><span class="lineno"> 843</span> </div><div class="line"><a name="l00844"></a><span class="lineno"> 844</span>  <span class="keywordtype">void</span> heap_pop() {</div><div class="line"><a name="l00845"></a><span class="lineno"> 845</span>  <span class="comment">// Remove the minimal element from the heap.</span></div><div class="line"><a name="l00846"></a><span class="lineno"> 846</span>  --size;</div><div class="line"><a name="l00847"></a><span class="lineno"> 847</span>  I[0] = I[size];</div><div class="line"><a name="l00848"></a><span class="lineno"> 848</span>  R[I[0]] = 0;</div><div class="line"><a name="l00849"></a><span class="lineno"> 849</span>  update_geq_(0);</div><div class="line"><a name="l00850"></a><span class="lineno"> 850</span>  }</div><div class="line"><a name="l00851"></a><span class="lineno"> 851</span> </div><div class="line"><a name="l00852"></a><span class="lineno"> 852</span>  <span class="keywordtype">void</span> <span class="keyword">remove</span>(t_index idx) {</div><div class="line"><a name="l00853"></a><span class="lineno"> 853</span>  <span class="comment">// Remove an element from the heap.</span></div><div class="line"><a name="l00854"></a><span class="lineno"> 854</span>  --size;</div><div class="line"><a name="l00855"></a><span class="lineno"> 855</span>  R[I[size]] = R[idx];</div><div class="line"><a name="l00856"></a><span class="lineno"> 856</span>  I[R[idx]] = I[size];</div><div class="line"><a name="l00857"></a><span class="lineno"> 857</span>  <span class="keywordflow">if</span> ( H(size)<=A[idx] ) {</div><div class="line"><a name="l00858"></a><span class="lineno"> 858</span>  update_leq_(R[idx]);</div><div class="line"><a name="l00859"></a><span class="lineno"> 859</span>  }</div><div class="line"><a name="l00860"></a><span class="lineno"> 860</span>  <span class="keywordflow">else</span> {</div><div class="line"><a name="l00861"></a><span class="lineno"> 861</span>  update_geq_(R[idx]);</div><div class="line"><a name="l00862"></a><span class="lineno"> 862</span>  }</div><div class="line"><a name="l00863"></a><span class="lineno"> 863</span>  }</div><div class="line"><a name="l00864"></a><span class="lineno"> 864</span> </div><div class="line"><a name="l00865"></a><span class="lineno"> 865</span>  <span class="keywordtype">void</span> replace ( <span class="keyword">const</span> t_index idxold, <span class="keyword">const</span> t_index idxnew,</div><div class="line"><a name="l00866"></a><span class="lineno"> 866</span>  <span class="keyword">const</span> t_float val) {</div><div class="line"><a name="l00867"></a><span class="lineno"> 867</span>  R[idxnew] = R[idxold];</div><div class="line"><a name="l00868"></a><span class="lineno"> 868</span>  I[R[idxnew]] = idxnew;</div><div class="line"><a name="l00869"></a><span class="lineno"> 869</span>  <span class="keywordflow">if</span> (val<=A[idxold])</div><div class="line"><a name="l00870"></a><span class="lineno"> 870</span>  update_leq(idxnew, val);</div><div class="line"><a name="l00871"></a><span class="lineno"> 871</span>  <span class="keywordflow">else</span></div><div class="line"><a name="l00872"></a><span class="lineno"> 872</span>  update_geq(idxnew, val);</div><div class="line"><a name="l00873"></a><span class="lineno"> 873</span>  }</div><div class="line"><a name="l00874"></a><span class="lineno"> 874</span> </div><div class="line"><a name="l00875"></a><span class="lineno"> 875</span>  <span class="keywordtype">void</span> update ( <span class="keyword">const</span> t_index idx, <span class="keyword">const</span> t_float val )<span class="keyword"> const </span>{</div><div class="line"><a name="l00876"></a><span class="lineno"> 876</span>  <span class="comment">// Update the element A[i] with val and re-arrange the indices to preserve</span></div><div class="line"><a name="l00877"></a><span class="lineno"> 877</span>  <span class="comment">// the heap condition.</span></div><div class="line"><a name="l00878"></a><span class="lineno"> 878</span>  <span class="keywordflow">if</span> (val<=A[idx])</div><div class="line"><a name="l00879"></a><span class="lineno"> 879</span>  update_leq(idx, val);</div><div class="line"><a name="l00880"></a><span class="lineno"> 880</span>  <span class="keywordflow">else</span></div><div class="line"><a name="l00881"></a><span class="lineno"> 881</span>  update_geq(idx, val);</div><div class="line"><a name="l00882"></a><span class="lineno"> 882</span>  }</div><div class="line"><a name="l00883"></a><span class="lineno"> 883</span> </div><div class="line"><a name="l00884"></a><span class="lineno"> 884</span>  <span class="keywordtype">void</span> update_leq ( <span class="keyword">const</span> t_index idx, <span class="keyword">const</span> t_float val )<span class="keyword"> const </span>{</div><div class="line"><a name="l00885"></a><span class="lineno"> 885</span>  <span class="comment">// Use this when the new value is not more than the old value.</span></div><div class="line"><a name="l00886"></a><span class="lineno"> 886</span>  A[idx] = val;</div><div class="line"><a name="l00887"></a><span class="lineno"> 887</span>  update_leq_(R[idx]);</div><div class="line"><a name="l00888"></a><span class="lineno"> 888</span>  }</div><div class="line"><a name="l00889"></a><span class="lineno"> 889</span> </div><div class="line"><a name="l00890"></a><span class="lineno"> 890</span>  <span class="keywordtype">void</span> update_geq ( <span class="keyword">const</span> t_index idx, <span class="keyword">const</span> t_float val )<span class="keyword"> const </span>{</div><div class="line"><a name="l00891"></a><span class="lineno"> 891</span>  <span class="comment">// Use this when the new value is not less than the old value.</span></div><div class="line"><a name="l00892"></a><span class="lineno"> 892</span>  A[idx] = val;</div><div class="line"><a name="l00893"></a><span class="lineno"> 893</span>  update_geq_(R[idx]);</div><div class="line"><a name="l00894"></a><span class="lineno"> 894</span>  }</div><div class="line"><a name="l00895"></a><span class="lineno"> 895</span> </div><div class="line"><a name="l00896"></a><span class="lineno"> 896</span> <span class="keyword">private</span>:</div><div class="line"><a name="l00897"></a><span class="lineno"> 897</span>  <span class="keywordtype">void</span> update_leq_ (t_index i)<span class="keyword"> const </span>{</div><div class="line"><a name="l00898"></a><span class="lineno"> 898</span>  t_index j;</div><div class="line"><a name="l00899"></a><span class="lineno"> 899</span>  <span class="keywordflow">for</span> ( ; (i>0) && ( H(i)<H(j=(i-1)>>1) ); i=j)</div><div class="line"><a name="l00900"></a><span class="lineno"> 900</span>  heap_swap(i,j);</div><div class="line"><a name="l00901"></a><span class="lineno"> 901</span>  }</div><div class="line"><a name="l00902"></a><span class="lineno"> 902</span> </div><div class="line"><a name="l00903"></a><span class="lineno"> 903</span>  <span class="keywordtype">void</span> update_geq_ (t_index i)<span class="keyword"> const </span>{</div><div class="line"><a name="l00904"></a><span class="lineno"> 904</span>  t_index j;</div><div class="line"><a name="l00905"></a><span class="lineno"> 905</span>  <span class="keywordflow">for</span> ( ; (j=2*i+1)<size; i=j) {</div><div class="line"><a name="l00906"></a><span class="lineno"> 906</span>  <span class="keywordflow">if</span> ( H(j)>=H(i) ) {</div><div class="line"><a name="l00907"></a><span class="lineno"> 907</span>  ++j;</div><div class="line"><a name="l00908"></a><span class="lineno"> 908</span>  <span class="keywordflow">if</span> ( j>=size || H(j)>=H(i) ) <span class="keywordflow">break</span>;</div><div class="line"><a name="l00909"></a><span class="lineno"> 909</span>  }</div><div class="line"><a name="l00910"></a><span class="lineno"> 910</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( j+1<size && H(j+1)<H(j) ) ++j;</div><div class="line"><a name="l00911"></a><span class="lineno"> 911</span>  heap_swap(i, j);</div><div class="line"><a name="l00912"></a><span class="lineno"> 912</span>  }</div><div class="line"><a name="l00913"></a><span class="lineno"> 913</span>  }</div><div class="line"><a name="l00914"></a><span class="lineno"> 914</span> </div><div class="line"><a name="l00915"></a><span class="lineno"> 915</span>  <span class="keywordtype">void</span> heap_swap(<span class="keyword">const</span> t_index i, <span class="keyword">const</span> t_index j)<span class="keyword"> const </span>{</div><div class="line"><a name="l00916"></a><span class="lineno"> 916</span>  <span class="comment">// Swap two indices.</span></div><div class="line"><a name="l00917"></a><span class="lineno"> 917</span>  t_index tmp = I[i];</div><div class="line"><a name="l00918"></a><span class="lineno"> 918</span>  I[i] = I[j];</div><div class="line"><a name="l00919"></a><span class="lineno"> 919</span>  I[j] = tmp;</div><div class="line"><a name="l00920"></a><span class="lineno"> 920</span>  R[I[i]] = i;</div><div class="line"><a name="l00921"></a><span class="lineno"> 921</span>  R[I[j]] = j;</div><div class="line"><a name="l00922"></a><span class="lineno"> 922</span>  }</div><div class="line"><a name="l00923"></a><span class="lineno"> 923</span> </div><div class="line"><a name="l00924"></a><span class="lineno"> 924</span>  <span class="keyword">inline</span> t_float H(<span class="keyword">const</span> t_index i)<span class="keyword"> const </span>{</div><div class="line"><a name="l00925"></a><span class="lineno"> 925</span>  <span class="keywordflow">return</span> A[I[i]];</div><div class="line"><a name="l00926"></a><span class="lineno"> 926</span>  }</div><div class="line"><a name="l00927"></a><span class="lineno"> 927</span> </div><div class="line"><a name="l00928"></a><span class="lineno"> 928</span> };</div><div class="line"><a name="l00929"></a><span class="lineno"> 929</span> </div><div class="line"><a name="l00930"></a><span class="lineno"> 930</span> <span class="keyword">template</span> <method_codes method, <span class="keyword">typename</span> t_members></div><div class="line"><a name="l00931"></a><span class="lineno"> 931</span> <span class="keyword">static</span> <span class="keywordtype">void</span> generic_linkage(<span class="keyword">const</span> t_index N, t_float * <span class="keyword">const</span> D, t_members * <span class="keyword">const</span> members, cluster_result & Z2) {</div><div class="line"><a name="l00932"></a><span class="lineno"> 932</span>  <span class="comment">/*</span></div><div class="line"><a name="l00933"></a><span class="lineno"> 933</span> <span class="comment"> N: integer, number of data points</span></div><div class="line"><a name="l00934"></a><span class="lineno"> 934</span> <span class="comment"> D: condensed distance matrix N*(N-1)/2</span></div><div class="line"><a name="l00935"></a><span class="lineno"> 935</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l00936"></a><span class="lineno"> 936</span> <span class="comment"> */</span></div><div class="line"><a name="l00937"></a><span class="lineno"> 937</span> </div><div class="line"><a name="l00938"></a><span class="lineno"> 938</span>  <span class="keyword">const</span> t_index N_1 = N-1;</div><div class="line"><a name="l00939"></a><span class="lineno"> 939</span>  t_index i, j; <span class="comment">// loop variables</span></div><div class="line"><a name="l00940"></a><span class="lineno"> 940</span>  t_index idx1, idx2; <span class="comment">// row and column indices</span></div><div class="line"><a name="l00941"></a><span class="lineno"> 941</span> </div><div class="line"><a name="l00942"></a><span class="lineno"> 942</span>  auto_array_ptr<t_index> n_nghbr(N_1); <span class="comment">// array of nearest neighbors</span></div><div class="line"><a name="l00943"></a><span class="lineno"> 943</span>  auto_array_ptr<t_float> mindist(N_1); <span class="comment">// distances to the nearest neighbors</span></div><div class="line"><a name="l00944"></a><span class="lineno"> 944</span>  auto_array_ptr<t_index> row_repr(N); <span class="comment">// row_repr[i]: node number that the</span></div><div class="line"><a name="l00945"></a><span class="lineno"> 945</span>  <span class="comment">// i-th row represents</span></div><div class="line"><a name="l00946"></a><span class="lineno"> 946</span>  doubly_linked_list active_nodes(N);</div><div class="line"><a name="l00947"></a><span class="lineno"> 947</span>  binary_min_heap nn_distances(&*mindist, N_1); <span class="comment">// minimum heap structure for</span></div><div class="line"><a name="l00948"></a><span class="lineno"> 948</span>  <span class="comment">// the distance to the nearest neighbor of each point</span></div><div class="line"><a name="l00949"></a><span class="lineno"> 949</span>  t_index node1, node2; <span class="comment">// node numbers in the output</span></div><div class="line"><a name="l00950"></a><span class="lineno"> 950</span>  t_float size1, size2; <span class="comment">// and their cardinalities</span></div><div class="line"><a name="l00951"></a><span class="lineno"> 951</span> </div><div class="line"><a name="l00952"></a><span class="lineno"> 952</span>  t_float min; <span class="comment">// minimum and row index for nearest-neighbor search</span></div><div class="line"><a name="l00953"></a><span class="lineno"> 953</span>  t_index idx;</div><div class="line"><a name="l00954"></a><span class="lineno"> 954</span> </div><div class="line"><a name="l00955"></a><span class="lineno"> 955</span>  <span class="keywordflow">for</span> (i=0; i<N; ++i)</div><div class="line"><a name="l00956"></a><span class="lineno"> 956</span>  <span class="comment">// Build a list of row ↔ node label assignments.</span></div><div class="line"><a name="l00957"></a><span class="lineno"> 957</span>  <span class="comment">// Initially i ↦ i</span></div><div class="line"><a name="l00958"></a><span class="lineno"> 958</span>  row_repr[i] = i;</div><div class="line"><a name="l00959"></a><span class="lineno"> 959</span> </div><div class="line"><a name="l00960"></a><span class="lineno"> 960</span>  <span class="comment">// Initialize the minimal distances:</span></div><div class="line"><a name="l00961"></a><span class="lineno"> 961</span>  <span class="comment">// Find the nearest neighbor of each point.</span></div><div class="line"><a name="l00962"></a><span class="lineno"> 962</span>  <span class="comment">// n_nghbr[i] = argmin_{j>i} D(i,j) for i in range(N-1)</span></div><div class="line"><a name="l00963"></a><span class="lineno"> 963</span>  t_float <span class="keyword">const</span> * DD = D;</div><div class="line"><a name="l00964"></a><span class="lineno"> 964</span>  <span class="keywordflow">for</span> (i=0; i<N_1; ++i) {</div><div class="line"><a name="l00965"></a><span class="lineno"> 965</span>  min = std::numeric_limits<t_float>::infinity();</div><div class="line"><a name="l00966"></a><span class="lineno"> 966</span>  <span class="keywordflow">for</span> (idx=j=i+1; j<N; ++j, ++DD) {</div><div class="line"><a name="l00967"></a><span class="lineno"> 967</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00968"></a><span class="lineno"> 968</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l00969"></a><span class="lineno"> 969</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l00970"></a><span class="lineno"> 970</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00971"></a><span class="lineno"> 971</span>  <span class="keywordflow">if</span> (*DD<min) {</div><div class="line"><a name="l00972"></a><span class="lineno"> 972</span>  min = *DD;</div><div class="line"><a name="l00973"></a><span class="lineno"> 973</span>  idx = j;</div><div class="line"><a name="l00974"></a><span class="lineno"> 974</span>  }</div><div class="line"><a name="l00975"></a><span class="lineno"> 975</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(*DD))</div><div class="line"><a name="l00976"></a><span class="lineno"> 976</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l00977"></a><span class="lineno"> 977</span>  }</div><div class="line"><a name="l00978"></a><span class="lineno"> 978</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l00979"></a><span class="lineno"> 979</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l00980"></a><span class="lineno"> 980</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00981"></a><span class="lineno"> 981</span>  mindist[i] = min;</div><div class="line"><a name="l00982"></a><span class="lineno"> 982</span>  n_nghbr[i] = idx;</div><div class="line"><a name="l00983"></a><span class="lineno"> 983</span>  }</div><div class="line"><a name="l00984"></a><span class="lineno"> 984</span> </div><div class="line"><a name="l00985"></a><span class="lineno"> 985</span>  <span class="comment">// Put the minimal distances into a heap structure to make the repeated</span></div><div class="line"><a name="l00986"></a><span class="lineno"> 986</span>  <span class="comment">// global minimum searches fast.</span></div><div class="line"><a name="l00987"></a><span class="lineno"> 987</span>  nn_distances.heapify();</div><div class="line"><a name="l00988"></a><span class="lineno"> 988</span> </div><div class="line"><a name="l00989"></a><span class="lineno"> 989</span> <span class="preprocessor"> #ifdef FE_INVALID</span></div><div class="line"><a name="l00990"></a><span class="lineno"> 990</span>  <span class="keywordflow">if</span> (feclearexcept(FE_INVALID)) <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: fenv error"</span>);</div><div class="line"><a name="l00991"></a><span class="lineno"> 991</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l00992"></a><span class="lineno"> 992</span> </div><div class="line"><a name="l00993"></a><span class="lineno"> 993</span>  <span class="comment">// Main loop: We have N-1 merging steps.</span></div><div class="line"><a name="l00994"></a><span class="lineno"> 994</span>  <span class="keywordflow">for</span> (i=0; i<N_1; ++i) {</div><div class="line"><a name="l00995"></a><span class="lineno"> 995</span>  <span class="comment">/*</span></div><div class="line"><a name="l00996"></a><span class="lineno"> 996</span> <span class="comment"> Here is a special feature that allows fast bookkeeping and updates of the</span></div><div class="line"><a name="l00997"></a><span class="lineno"> 997</span> <span class="comment"> minimal distances.</span></div><div class="line"><a name="l00998"></a><span class="lineno"> 998</span> <span class="comment"></span></div><div class="line"><a name="l00999"></a><span class="lineno"> 999</span> <span class="comment"> mindist[i] stores a lower bound on the minimum distance of the point i to</span></div><div class="line"><a name="l01000"></a><span class="lineno"> 1000</span> <span class="comment"> all points of higher index:</span></div><div class="line"><a name="l01001"></a><span class="lineno"> 1001</span> <span class="comment"></span></div><div class="line"><a name="l01002"></a><span class="lineno"> 1002</span> <span class="comment"> mindist[i] ≥ min_{j>i} D(i,j)</span></div><div class="line"><a name="l01003"></a><span class="lineno"> 1003</span> <span class="comment"></span></div><div class="line"><a name="l01004"></a><span class="lineno"> 1004</span> <span class="comment"> Normally, we have equality. However, this minimum may become invalid due</span></div><div class="line"><a name="l01005"></a><span class="lineno"> 1005</span> <span class="comment"> to the updates in the distance matrix. The rules are:</span></div><div class="line"><a name="l01006"></a><span class="lineno"> 1006</span> <span class="comment"></span></div><div class="line"><a name="l01007"></a><span class="lineno"> 1007</span> <span class="comment"> 1) If mindist[i] is equal to D(i, n_nghbr[i]), this is the correct</span></div><div class="line"><a name="l01008"></a><span class="lineno"> 1008</span> <span class="comment"> minimum and n_nghbr[i] is a nearest neighbor.</span></div><div class="line"><a name="l01009"></a><span class="lineno"> 1009</span> <span class="comment"></span></div><div class="line"><a name="l01010"></a><span class="lineno"> 1010</span> <span class="comment"> 2) If mindist[i] is smaller than D(i, n_nghbr[i]), this might not be the</span></div><div class="line"><a name="l01011"></a><span class="lineno"> 1011</span> <span class="comment"> correct minimum. The minimum needs to be recomputed.</span></div><div class="line"><a name="l01012"></a><span class="lineno"> 1012</span> <span class="comment"></span></div><div class="line"><a name="l01013"></a><span class="lineno"> 1013</span> <span class="comment"> 3) mindist[i] is never bigger than the true minimum. Hence, we never</span></div><div class="line"><a name="l01014"></a><span class="lineno"> 1014</span> <span class="comment"> miss the true minimum if we take the smallest mindist entry,</span></div><div class="line"><a name="l01015"></a><span class="lineno"> 1015</span> <span class="comment"> re-compute the value if necessary (thus maybe increasing it) and</span></div><div class="line"><a name="l01016"></a><span class="lineno"> 1016</span> <span class="comment"> looking for the now smallest mindist entry until a valid minimal</span></div><div class="line"><a name="l01017"></a><span class="lineno"> 1017</span> <span class="comment"> entry is found. This step is done in the lines below.</span></div><div class="line"><a name="l01018"></a><span class="lineno"> 1018</span> <span class="comment"></span></div><div class="line"><a name="l01019"></a><span class="lineno"> 1019</span> <span class="comment"> The update process for D below takes care that these rules are</span></div><div class="line"><a name="l01020"></a><span class="lineno"> 1020</span> <span class="comment"> fulfilled. This makes sure that the minima in the rows D(i,i+1:)of D are</span></div><div class="line"><a name="l01021"></a><span class="lineno"> 1021</span> <span class="comment"> re-calculated when necessary but re-calculation is avoided whenever</span></div><div class="line"><a name="l01022"></a><span class="lineno"> 1022</span> <span class="comment"> possible.</span></div><div class="line"><a name="l01023"></a><span class="lineno"> 1023</span> <span class="comment"></span></div><div class="line"><a name="l01024"></a><span class="lineno"> 1024</span> <span class="comment"> The re-calculation of the minima makes the worst-case runtime of this</span></div><div class="line"><a name="l01025"></a><span class="lineno"> 1025</span> <span class="comment"> algorithm cubic in N. We avoid this whenever possible, and in most cases</span></div><div class="line"><a name="l01026"></a><span class="lineno"> 1026</span> <span class="comment"> the runtime appears to be quadratic.</span></div><div class="line"><a name="l01027"></a><span class="lineno"> 1027</span> <span class="comment"> */</span></div><div class="line"><a name="l01028"></a><span class="lineno"> 1028</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01029"></a><span class="lineno"> 1029</span>  <span class="keywordflow">if</span> (method != METHOD_METR_SINGLE) {</div><div class="line"><a name="l01030"></a><span class="lineno"> 1030</span>  <span class="keywordflow">while</span> ( mindist[idx1] < D_(idx1, n_nghbr[idx1]) ) {</div><div class="line"><a name="l01031"></a><span class="lineno"> 1031</span>  <span class="comment">// Recompute the minimum mindist[idx1] and n_nghbr[idx1].</span></div><div class="line"><a name="l01032"></a><span class="lineno"> 1032</span>  n_nghbr[idx1] = j = active_nodes.succ[idx1]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01033"></a><span class="lineno"> 1033</span>  min = D_(idx1,j);</div><div class="line"><a name="l01034"></a><span class="lineno"> 1034</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01035"></a><span class="lineno"> 1035</span>  <span class="keywordflow">if</span> (D_(idx1,j)<min) {</div><div class="line"><a name="l01036"></a><span class="lineno"> 1036</span>  min = D_(idx1,j);</div><div class="line"><a name="l01037"></a><span class="lineno"> 1037</span>  n_nghbr[idx1] = j;</div><div class="line"><a name="l01038"></a><span class="lineno"> 1038</span>  }</div><div class="line"><a name="l01039"></a><span class="lineno"> 1039</span>  }</div><div class="line"><a name="l01040"></a><span class="lineno"> 1040</span>  <span class="comment">/* Update the heap with the new true minimum and search for the</span></div><div class="line"><a name="l01041"></a><span class="lineno"> 1041</span> <span class="comment"> (possibly different) minimal entry. */</span></div><div class="line"><a name="l01042"></a><span class="lineno"> 1042</span>  nn_distances.update_geq(idx1, min);</div><div class="line"><a name="l01043"></a><span class="lineno"> 1043</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01044"></a><span class="lineno"> 1044</span>  }</div><div class="line"><a name="l01045"></a><span class="lineno"> 1045</span>  }</div><div class="line"><a name="l01046"></a><span class="lineno"> 1046</span> </div><div class="line"><a name="l01047"></a><span class="lineno"> 1047</span>  nn_distances.heap_pop(); <span class="comment">// Remove the current minimum from the heap.</span></div><div class="line"><a name="l01048"></a><span class="lineno"> 1048</span>  idx2 = n_nghbr[idx1];</div><div class="line"><a name="l01049"></a><span class="lineno"> 1049</span> </div><div class="line"><a name="l01050"></a><span class="lineno"> 1050</span>  <span class="comment">// Write the newly found minimal pair of nodes to the output array.</span></div><div class="line"><a name="l01051"></a><span class="lineno"> 1051</span>  node1 = row_repr[idx1];</div><div class="line"><a name="l01052"></a><span class="lineno"> 1052</span>  node2 = row_repr[idx2];</div><div class="line"><a name="l01053"></a><span class="lineno"> 1053</span> </div><div class="line"><a name="l01054"></a><span class="lineno"> 1054</span>  <span class="keywordflow">if</span> (method==METHOD_METR_AVERAGE ||</div><div class="line"><a name="l01055"></a><span class="lineno"> 1055</span>  method==METHOD_METR_WARD ||</div><div class="line"><a name="l01056"></a><span class="lineno"> 1056</span>  method==METHOD_METR_CENTROID) {</div><div class="line"><a name="l01057"></a><span class="lineno"> 1057</span>  size1 = <span class="keyword">static_cast<</span>t_float<span class="keyword">></span>(members[idx1]);</div><div class="line"><a name="l01058"></a><span class="lineno"> 1058</span>  size2 = <span class="keyword">static_cast<</span>t_float<span class="keyword">></span>(members[idx2]);</div><div class="line"><a name="l01059"></a><span class="lineno"> 1059</span>  members[idx2] += members[idx1];</div><div class="line"><a name="l01060"></a><span class="lineno"> 1060</span>  }</div><div class="line"><a name="l01061"></a><span class="lineno"> 1061</span>  Z2.append(node1, node2, mindist[idx1]);</div><div class="line"><a name="l01062"></a><span class="lineno"> 1062</span> </div><div class="line"><a name="l01063"></a><span class="lineno"> 1063</span>  <span class="comment">// Remove idx1 from the list of active indices (active_nodes).</span></div><div class="line"><a name="l01064"></a><span class="lineno"> 1064</span>  active_nodes.remove(idx1);</div><div class="line"><a name="l01065"></a><span class="lineno"> 1065</span>  <span class="comment">// Index idx2 now represents the new (merged) node with label N+i.</span></div><div class="line"><a name="l01066"></a><span class="lineno"> 1066</span>  row_repr[idx2] = N+i;</div><div class="line"><a name="l01067"></a><span class="lineno"> 1067</span> </div><div class="line"><a name="l01068"></a><span class="lineno"> 1068</span>  <span class="comment">// Update the distance matrix</span></div><div class="line"><a name="l01069"></a><span class="lineno"> 1069</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01070"></a><span class="lineno"> 1070</span>  <span class="keywordflow">case</span> METHOD_METR_SINGLE:</div><div class="line"><a name="l01071"></a><span class="lineno"> 1071</span>  <span class="comment">/*</span></div><div class="line"><a name="l01072"></a><span class="lineno"> 1072</span> <span class="comment"> Single linkage.</span></div><div class="line"><a name="l01073"></a><span class="lineno"> 1073</span> <span class="comment"></span></div><div class="line"><a name="l01074"></a><span class="lineno"> 1074</span> <span class="comment"> Characteristic: new distances are never longer than the old distances.</span></div><div class="line"><a name="l01075"></a><span class="lineno"> 1075</span> <span class="comment"> */</span></div><div class="line"><a name="l01076"></a><span class="lineno"> 1076</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01077"></a><span class="lineno"> 1077</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01078"></a><span class="lineno"> 1078</span>  f_single(&D_(j, idx2), D_(j, idx1));</div><div class="line"><a name="l01079"></a><span class="lineno"> 1079</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01080"></a><span class="lineno"> 1080</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01081"></a><span class="lineno"> 1081</span>  }</div><div class="line"><a name="l01082"></a><span class="lineno"> 1082</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01083"></a><span class="lineno"> 1083</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01084"></a><span class="lineno"> 1084</span>  f_single(&D_(j, idx2), D_(idx1, j));</div><div class="line"><a name="l01085"></a><span class="lineno"> 1085</span>  <span class="comment">// If the new value is below the old minimum in a row, update</span></div><div class="line"><a name="l01086"></a><span class="lineno"> 1086</span>  <span class="comment">// the mindist and n_nghbr arrays.</span></div><div class="line"><a name="l01087"></a><span class="lineno"> 1087</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01088"></a><span class="lineno"> 1088</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01089"></a><span class="lineno"> 1089</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01090"></a><span class="lineno"> 1090</span>  }</div><div class="line"><a name="l01091"></a><span class="lineno"> 1091</span>  }</div><div class="line"><a name="l01092"></a><span class="lineno"> 1092</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01093"></a><span class="lineno"> 1093</span>  <span class="comment">// Recompute the minimum mindist[idx2] and n_nghbr[idx2].</span></div><div class="line"><a name="l01094"></a><span class="lineno"> 1094</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01095"></a><span class="lineno"> 1095</span>  min = mindist[idx2];</div><div class="line"><a name="l01096"></a><span class="lineno"> 1096</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[idx2]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01097"></a><span class="lineno"> 1097</span>  f_single(&D_(idx2, j), D_(idx1, j) );</div><div class="line"><a name="l01098"></a><span class="lineno"> 1098</span>  <span class="keywordflow">if</span> (D_(idx2, j) < min) {</div><div class="line"><a name="l01099"></a><span class="lineno"> 1099</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01100"></a><span class="lineno"> 1100</span>  min = D_(idx2, j);</div><div class="line"><a name="l01101"></a><span class="lineno"> 1101</span>  }</div><div class="line"><a name="l01102"></a><span class="lineno"> 1102</span>  }</div><div class="line"><a name="l01103"></a><span class="lineno"> 1103</span>  nn_distances.update_leq(idx2, min);</div><div class="line"><a name="l01104"></a><span class="lineno"> 1104</span>  }</div><div class="line"><a name="l01105"></a><span class="lineno"> 1105</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01106"></a><span class="lineno"> 1106</span> </div><div class="line"><a name="l01107"></a><span class="lineno"> 1107</span>  <span class="keywordflow">case</span> METHOD_METR_COMPLETE:</div><div class="line"><a name="l01108"></a><span class="lineno"> 1108</span>  <span class="comment">/*</span></div><div class="line"><a name="l01109"></a><span class="lineno"> 1109</span> <span class="comment"> Complete linkage.</span></div><div class="line"><a name="l01110"></a><span class="lineno"> 1110</span> <span class="comment"></span></div><div class="line"><a name="l01111"></a><span class="lineno"> 1111</span> <span class="comment"> Characteristic: new distances are never shorter than the old distances.</span></div><div class="line"><a name="l01112"></a><span class="lineno"> 1112</span> <span class="comment"> */</span></div><div class="line"><a name="l01113"></a><span class="lineno"> 1113</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01114"></a><span class="lineno"> 1114</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01115"></a><span class="lineno"> 1115</span>  f_complete(&D_(j, idx2), D_(j, idx1) );</div><div class="line"><a name="l01116"></a><span class="lineno"> 1116</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01117"></a><span class="lineno"> 1117</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01118"></a><span class="lineno"> 1118</span>  }</div><div class="line"><a name="l01119"></a><span class="lineno"> 1119</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01120"></a><span class="lineno"> 1120</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j])</div><div class="line"><a name="l01121"></a><span class="lineno"> 1121</span>  f_complete(&D_(j, idx2), D_(idx1, j) );</div><div class="line"><a name="l01122"></a><span class="lineno"> 1122</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01123"></a><span class="lineno"> 1123</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[idx2]; j<N; j=active_nodes.succ[j])</div><div class="line"><a name="l01124"></a><span class="lineno"> 1124</span>  f_complete(&D_(idx2, j), D_(idx1, j) );</div><div class="line"><a name="l01125"></a><span class="lineno"> 1125</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01126"></a><span class="lineno"> 1126</span> </div><div class="line"><a name="l01127"></a><span class="lineno"> 1127</span>  <span class="keywordflow">case</span> METHOD_METR_AVERAGE: {</div><div class="line"><a name="l01128"></a><span class="lineno"> 1128</span>  <span class="comment">/*</span></div><div class="line"><a name="l01129"></a><span class="lineno"> 1129</span> <span class="comment"> Average linkage.</span></div><div class="line"><a name="l01130"></a><span class="lineno"> 1130</span> <span class="comment"></span></div><div class="line"><a name="l01131"></a><span class="lineno"> 1131</span> <span class="comment"> Shorter and longer distances can occur.</span></div><div class="line"><a name="l01132"></a><span class="lineno"> 1132</span> <span class="comment"> */</span></div><div class="line"><a name="l01133"></a><span class="lineno"> 1133</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01134"></a><span class="lineno"> 1134</span>  t_float s = size1/(size1+size2);</div><div class="line"><a name="l01135"></a><span class="lineno"> 1135</span>  t_float t = size2/(size1+size2);</div><div class="line"><a name="l01136"></a><span class="lineno"> 1136</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01137"></a><span class="lineno"> 1137</span>  f_average(&D_(j, idx2), D_(j, idx1), s, t);</div><div class="line"><a name="l01138"></a><span class="lineno"> 1138</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01139"></a><span class="lineno"> 1139</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01140"></a><span class="lineno"> 1140</span>  }</div><div class="line"><a name="l01141"></a><span class="lineno"> 1141</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01142"></a><span class="lineno"> 1142</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01143"></a><span class="lineno"> 1143</span>  f_average(&D_(j, idx2), D_(idx1, j), s, t);</div><div class="line"><a name="l01144"></a><span class="lineno"> 1144</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01145"></a><span class="lineno"> 1145</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01146"></a><span class="lineno"> 1146</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01147"></a><span class="lineno"> 1147</span>  }</div><div class="line"><a name="l01148"></a><span class="lineno"> 1148</span>  }</div><div class="line"><a name="l01149"></a><span class="lineno"> 1149</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01150"></a><span class="lineno"> 1150</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01151"></a><span class="lineno"> 1151</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01152"></a><span class="lineno"> 1152</span>  f_average(&D_(idx2, j), D_(idx1, j), s, t);</div><div class="line"><a name="l01153"></a><span class="lineno"> 1153</span>  min = D_(idx2,j);</div><div class="line"><a name="l01154"></a><span class="lineno"> 1154</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01155"></a><span class="lineno"> 1155</span>  f_average(&D_(idx2, j), D_(idx1, j), s, t);</div><div class="line"><a name="l01156"></a><span class="lineno"> 1156</span>  <span class="keywordflow">if</span> (D_(idx2,j) < min) {</div><div class="line"><a name="l01157"></a><span class="lineno"> 1157</span>  min = D_(idx2,j);</div><div class="line"><a name="l01158"></a><span class="lineno"> 1158</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01159"></a><span class="lineno"> 1159</span>  }</div><div class="line"><a name="l01160"></a><span class="lineno"> 1160</span>  }</div><div class="line"><a name="l01161"></a><span class="lineno"> 1161</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01162"></a><span class="lineno"> 1162</span>  }</div><div class="line"><a name="l01163"></a><span class="lineno"> 1163</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01164"></a><span class="lineno"> 1164</span>  }</div><div class="line"><a name="l01165"></a><span class="lineno"> 1165</span> </div><div class="line"><a name="l01166"></a><span class="lineno"> 1166</span>  <span class="keywordflow">case</span> METHOD_METR_WEIGHTED:</div><div class="line"><a name="l01167"></a><span class="lineno"> 1167</span>  <span class="comment">/*</span></div><div class="line"><a name="l01168"></a><span class="lineno"> 1168</span> <span class="comment"> Weighted linkage.</span></div><div class="line"><a name="l01169"></a><span class="lineno"> 1169</span> <span class="comment"></span></div><div class="line"><a name="l01170"></a><span class="lineno"> 1170</span> <span class="comment"> Shorter and longer distances can occur.</span></div><div class="line"><a name="l01171"></a><span class="lineno"> 1171</span> <span class="comment"> */</span></div><div class="line"><a name="l01172"></a><span class="lineno"> 1172</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01173"></a><span class="lineno"> 1173</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01174"></a><span class="lineno"> 1174</span>  f_weighted(&D_(j, idx2), D_(j, idx1) );</div><div class="line"><a name="l01175"></a><span class="lineno"> 1175</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01176"></a><span class="lineno"> 1176</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01177"></a><span class="lineno"> 1177</span>  }</div><div class="line"><a name="l01178"></a><span class="lineno"> 1178</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01179"></a><span class="lineno"> 1179</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01180"></a><span class="lineno"> 1180</span>  f_weighted(&D_(j, idx2), D_(idx1, j) );</div><div class="line"><a name="l01181"></a><span class="lineno"> 1181</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01182"></a><span class="lineno"> 1182</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01183"></a><span class="lineno"> 1183</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01184"></a><span class="lineno"> 1184</span>  }</div><div class="line"><a name="l01185"></a><span class="lineno"> 1185</span>  }</div><div class="line"><a name="l01186"></a><span class="lineno"> 1186</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01187"></a><span class="lineno"> 1187</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01188"></a><span class="lineno"> 1188</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01189"></a><span class="lineno"> 1189</span>  f_weighted(&D_(idx2, j), D_(idx1, j) );</div><div class="line"><a name="l01190"></a><span class="lineno"> 1190</span>  min = D_(idx2,j);</div><div class="line"><a name="l01191"></a><span class="lineno"> 1191</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01192"></a><span class="lineno"> 1192</span>  f_weighted(&D_(idx2, j), D_(idx1, j) );</div><div class="line"><a name="l01193"></a><span class="lineno"> 1193</span>  <span class="keywordflow">if</span> (D_(idx2,j) < min) {</div><div class="line"><a name="l01194"></a><span class="lineno"> 1194</span>  min = D_(idx2,j);</div><div class="line"><a name="l01195"></a><span class="lineno"> 1195</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01196"></a><span class="lineno"> 1196</span>  }</div><div class="line"><a name="l01197"></a><span class="lineno"> 1197</span>  }</div><div class="line"><a name="l01198"></a><span class="lineno"> 1198</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01199"></a><span class="lineno"> 1199</span>  }</div><div class="line"><a name="l01200"></a><span class="lineno"> 1200</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01201"></a><span class="lineno"> 1201</span> </div><div class="line"><a name="l01202"></a><span class="lineno"> 1202</span>  <span class="keywordflow">case</span> METHOD_METR_WARD:</div><div class="line"><a name="l01203"></a><span class="lineno"> 1203</span>  <span class="comment">/*</span></div><div class="line"><a name="l01204"></a><span class="lineno"> 1204</span> <span class="comment"> Ward linkage.</span></div><div class="line"><a name="l01205"></a><span class="lineno"> 1205</span> <span class="comment"></span></div><div class="line"><a name="l01206"></a><span class="lineno"> 1206</span> <span class="comment"> Shorter and longer distances can occur, not smaller than min(d1,d2)</span></div><div class="line"><a name="l01207"></a><span class="lineno"> 1207</span> <span class="comment"> but maybe bigger than max(d1,d2).</span></div><div class="line"><a name="l01208"></a><span class="lineno"> 1208</span> <span class="comment"> */</span></div><div class="line"><a name="l01209"></a><span class="lineno"> 1209</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01210"></a><span class="lineno"> 1210</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01211"></a><span class="lineno"> 1211</span>  f_ward(&D_(j, idx2), D_(j, idx1), mindist[idx1],</div><div class="line"><a name="l01212"></a><span class="lineno"> 1212</span>  size1, size2, static_cast<t_float>(members[j]) );</div><div class="line"><a name="l01213"></a><span class="lineno"> 1213</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01214"></a><span class="lineno"> 1214</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01215"></a><span class="lineno"> 1215</span>  }</div><div class="line"><a name="l01216"></a><span class="lineno"> 1216</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01217"></a><span class="lineno"> 1217</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01218"></a><span class="lineno"> 1218</span>  f_ward(&D_(j, idx2), D_(idx1, j), mindist[idx1], size1, size2,</div><div class="line"><a name="l01219"></a><span class="lineno"> 1219</span>  static_cast<t_float>(members[j]) );</div><div class="line"><a name="l01220"></a><span class="lineno"> 1220</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01221"></a><span class="lineno"> 1221</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01222"></a><span class="lineno"> 1222</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01223"></a><span class="lineno"> 1223</span>  }</div><div class="line"><a name="l01224"></a><span class="lineno"> 1224</span>  }</div><div class="line"><a name="l01225"></a><span class="lineno"> 1225</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01226"></a><span class="lineno"> 1226</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01227"></a><span class="lineno"> 1227</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01228"></a><span class="lineno"> 1228</span>  f_ward(&D_(idx2, j), D_(idx1, j), mindist[idx1],</div><div class="line"><a name="l01229"></a><span class="lineno"> 1229</span>  size1, size2, static_cast<t_float>(members[j]) );</div><div class="line"><a name="l01230"></a><span class="lineno"> 1230</span>  min = D_(idx2,j);</div><div class="line"><a name="l01231"></a><span class="lineno"> 1231</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01232"></a><span class="lineno"> 1232</span>  f_ward(&D_(idx2, j), D_(idx1, j), mindist[idx1],</div><div class="line"><a name="l01233"></a><span class="lineno"> 1233</span>  size1, size2, static_cast<t_float>(members[j]) );</div><div class="line"><a name="l01234"></a><span class="lineno"> 1234</span>  <span class="keywordflow">if</span> (D_(idx2,j) < min) {</div><div class="line"><a name="l01235"></a><span class="lineno"> 1235</span>  min = D_(idx2,j);</div><div class="line"><a name="l01236"></a><span class="lineno"> 1236</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01237"></a><span class="lineno"> 1237</span>  }</div><div class="line"><a name="l01238"></a><span class="lineno"> 1238</span>  }</div><div class="line"><a name="l01239"></a><span class="lineno"> 1239</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01240"></a><span class="lineno"> 1240</span>  }</div><div class="line"><a name="l01241"></a><span class="lineno"> 1241</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01242"></a><span class="lineno"> 1242</span> </div><div class="line"><a name="l01243"></a><span class="lineno"> 1243</span>  <span class="keywordflow">case</span> METHOD_METR_CENTROID: {</div><div class="line"><a name="l01244"></a><span class="lineno"> 1244</span>  <span class="comment">/*</span></div><div class="line"><a name="l01245"></a><span class="lineno"> 1245</span> <span class="comment"> Centroid linkage.</span></div><div class="line"><a name="l01246"></a><span class="lineno"> 1246</span> <span class="comment"></span></div><div class="line"><a name="l01247"></a><span class="lineno"> 1247</span> <span class="comment"> Shorter and longer distances can occur, not bigger than max(d1,d2)</span></div><div class="line"><a name="l01248"></a><span class="lineno"> 1248</span> <span class="comment"> but maybe smaller than min(d1,d2).</span></div><div class="line"><a name="l01249"></a><span class="lineno"> 1249</span> <span class="comment"> */</span></div><div class="line"><a name="l01250"></a><span class="lineno"> 1250</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01251"></a><span class="lineno"> 1251</span>  t_float s = size1/(size1+size2);</div><div class="line"><a name="l01252"></a><span class="lineno"> 1252</span>  t_float t = size2/(size1+size2);</div><div class="line"><a name="l01253"></a><span class="lineno"> 1253</span>  t_float stc = s*t*mindist[idx1];</div><div class="line"><a name="l01254"></a><span class="lineno"> 1254</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01255"></a><span class="lineno"> 1255</span>  f_centroid(&D_(j, idx2), D_(j, idx1), stc, s, t);</div><div class="line"><a name="l01256"></a><span class="lineno"> 1256</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01257"></a><span class="lineno"> 1257</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01258"></a><span class="lineno"> 1258</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01259"></a><span class="lineno"> 1259</span>  }</div><div class="line"><a name="l01260"></a><span class="lineno"> 1260</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01261"></a><span class="lineno"> 1261</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01262"></a><span class="lineno"> 1262</span>  }</div><div class="line"><a name="l01263"></a><span class="lineno"> 1263</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01264"></a><span class="lineno"> 1264</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01265"></a><span class="lineno"> 1265</span>  f_centroid(&D_(j, idx2), D_(idx1, j), stc, s, t);</div><div class="line"><a name="l01266"></a><span class="lineno"> 1266</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01267"></a><span class="lineno"> 1267</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01268"></a><span class="lineno"> 1268</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01269"></a><span class="lineno"> 1269</span>  }</div><div class="line"><a name="l01270"></a><span class="lineno"> 1270</span>  }</div><div class="line"><a name="l01271"></a><span class="lineno"> 1271</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01272"></a><span class="lineno"> 1272</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01273"></a><span class="lineno"> 1273</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01274"></a><span class="lineno"> 1274</span>  f_centroid(&D_(idx2, j), D_(idx1, j), stc, s, t);</div><div class="line"><a name="l01275"></a><span class="lineno"> 1275</span>  min = D_(idx2,j);</div><div class="line"><a name="l01276"></a><span class="lineno"> 1276</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01277"></a><span class="lineno"> 1277</span>  f_centroid(&D_(idx2, j), D_(idx1, j), stc, s, t);</div><div class="line"><a name="l01278"></a><span class="lineno"> 1278</span>  <span class="keywordflow">if</span> (D_(idx2,j) < min) {</div><div class="line"><a name="l01279"></a><span class="lineno"> 1279</span>  min = D_(idx2,j);</div><div class="line"><a name="l01280"></a><span class="lineno"> 1280</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01281"></a><span class="lineno"> 1281</span>  }</div><div class="line"><a name="l01282"></a><span class="lineno"> 1282</span>  }</div><div class="line"><a name="l01283"></a><span class="lineno"> 1283</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01284"></a><span class="lineno"> 1284</span>  }</div><div class="line"><a name="l01285"></a><span class="lineno"> 1285</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01286"></a><span class="lineno"> 1286</span>  }</div><div class="line"><a name="l01287"></a><span class="lineno"> 1287</span> </div><div class="line"><a name="l01288"></a><span class="lineno"> 1288</span>  <span class="keywordflow">case</span> METHOD_METR_MEDIAN: {</div><div class="line"><a name="l01289"></a><span class="lineno"> 1289</span>  <span class="comment">/*</span></div><div class="line"><a name="l01290"></a><span class="lineno"> 1290</span> <span class="comment"> Median linkage.</span></div><div class="line"><a name="l01291"></a><span class="lineno"> 1291</span> <span class="comment"></span></div><div class="line"><a name="l01292"></a><span class="lineno"> 1292</span> <span class="comment"> Shorter and longer distances can occur, not bigger than max(d1,d2)</span></div><div class="line"><a name="l01293"></a><span class="lineno"> 1293</span> <span class="comment"> but maybe smaller than min(d1,d2).</span></div><div class="line"><a name="l01294"></a><span class="lineno"> 1294</span> <span class="comment"> */</span></div><div class="line"><a name="l01295"></a><span class="lineno"> 1295</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01296"></a><span class="lineno"> 1296</span>  t_float c_4 = mindist[idx1]*.25;</div><div class="line"><a name="l01297"></a><span class="lineno"> 1297</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01298"></a><span class="lineno"> 1298</span>  f_median(&D_(j, idx2), D_(j, idx1), c_4 );</div><div class="line"><a name="l01299"></a><span class="lineno"> 1299</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01300"></a><span class="lineno"> 1300</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01301"></a><span class="lineno"> 1301</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01302"></a><span class="lineno"> 1302</span>  }</div><div class="line"><a name="l01303"></a><span class="lineno"> 1303</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n_nghbr[j] == idx1)</div><div class="line"><a name="l01304"></a><span class="lineno"> 1304</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01305"></a><span class="lineno"> 1305</span>  }</div><div class="line"><a name="l01306"></a><span class="lineno"> 1306</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01307"></a><span class="lineno"> 1307</span>  <span class="keywordflow">for</span> (; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01308"></a><span class="lineno"> 1308</span>  f_median(&D_(j, idx2), D_(idx1, j), c_4 );</div><div class="line"><a name="l01309"></a><span class="lineno"> 1309</span>  <span class="keywordflow">if</span> (D_(j, idx2) < mindist[j]) {</div><div class="line"><a name="l01310"></a><span class="lineno"> 1310</span>  nn_distances.update_leq(j, D_(j, idx2));</div><div class="line"><a name="l01311"></a><span class="lineno"> 1311</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01312"></a><span class="lineno"> 1312</span>  }</div><div class="line"><a name="l01313"></a><span class="lineno"> 1313</span>  }</div><div class="line"><a name="l01314"></a><span class="lineno"> 1314</span>  <span class="comment">// Update the distance matrix in the range (idx2, N).</span></div><div class="line"><a name="l01315"></a><span class="lineno"> 1315</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01316"></a><span class="lineno"> 1316</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01317"></a><span class="lineno"> 1317</span>  f_median(&D_(idx2, j), D_(idx1, j), c_4 );</div><div class="line"><a name="l01318"></a><span class="lineno"> 1318</span>  min = D_(idx2,j);</div><div class="line"><a name="l01319"></a><span class="lineno"> 1319</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01320"></a><span class="lineno"> 1320</span>  f_median(&D_(idx2, j), D_(idx1, j), c_4 );</div><div class="line"><a name="l01321"></a><span class="lineno"> 1321</span>  <span class="keywordflow">if</span> (D_(idx2,j) < min) {</div><div class="line"><a name="l01322"></a><span class="lineno"> 1322</span>  min = D_(idx2,j);</div><div class="line"><a name="l01323"></a><span class="lineno"> 1323</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01324"></a><span class="lineno"> 1324</span>  }</div><div class="line"><a name="l01325"></a><span class="lineno"> 1325</span>  }</div><div class="line"><a name="l01326"></a><span class="lineno"> 1326</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01327"></a><span class="lineno"> 1327</span>  }</div><div class="line"><a name="l01328"></a><span class="lineno"> 1328</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01329"></a><span class="lineno"> 1329</span>  }</div><div class="line"><a name="l01330"></a><span class="lineno"> 1330</span> </div><div class="line"><a name="l01331"></a><span class="lineno"> 1331</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01332"></a><span class="lineno"> 1332</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: invalid method"</span>);</div><div class="line"><a name="l01333"></a><span class="lineno"> 1333</span>  }</div><div class="line"><a name="l01334"></a><span class="lineno"> 1334</span>  }</div><div class="line"><a name="l01335"></a><span class="lineno"> 1335</span> <span class="preprocessor"> #ifdef FE_INVALID</span></div><div class="line"><a name="l01336"></a><span class="lineno"> 1336</span>  <span class="keywordflow">if</span> (fetestexcept(FE_INVALID)) <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: fenv error"</span>);</div><div class="line"><a name="l01337"></a><span class="lineno"> 1337</span> <span class="preprocessor"> #endif</span></div><div class="line"><a name="l01338"></a><span class="lineno"> 1338</span> }</div><div class="line"><a name="l01339"></a><span class="lineno"> 1339</span> </div><div class="line"><a name="l01340"></a><span class="lineno"> 1340</span> <span class="comment">/*</span></div><div class="line"><a name="l01341"></a><span class="lineno"> 1341</span> <span class="comment"> Clustering methods for vector data</span></div><div class="line"><a name="l01342"></a><span class="lineno"> 1342</span> <span class="comment">*/</span></div><div class="line"><a name="l01343"></a><span class="lineno"> 1343</span> </div><div class="line"><a name="l01344"></a><span class="lineno"> 1344</span> <span class="keyword">template</span> <<span class="keyword">typename</span> t_dissimilarity></div><div class="line"><a name="l01345"></a><span class="lineno"> 1345</span> <span class="keyword">static</span> <span class="keywordtype">void</span> MST_linkage_core_vector(<span class="keyword">const</span> t_index N,</div><div class="line"><a name="l01346"></a><span class="lineno"> 1346</span>  t_dissimilarity & dist,</div><div class="line"><a name="l01347"></a><span class="lineno"> 1347</span>  cluster_result & Z2) {</div><div class="line"><a name="l01348"></a><span class="lineno"> 1348</span> <span class="comment">/*</span></div><div class="line"><a name="l01349"></a><span class="lineno"> 1349</span> <span class="comment"> N: integer, number of data points</span></div><div class="line"><a name="l01350"></a><span class="lineno"> 1350</span> <span class="comment"> dist: function pointer to the metric</span></div><div class="line"><a name="l01351"></a><span class="lineno"> 1351</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l01352"></a><span class="lineno"> 1352</span> <span class="comment"></span></div><div class="line"><a name="l01353"></a><span class="lineno"> 1353</span> <span class="comment"> The basis of this algorithm is an algorithm by Rohlf:</span></div><div class="line"><a name="l01354"></a><span class="lineno"> 1354</span> <span class="comment"></span></div><div class="line"><a name="l01355"></a><span class="lineno"> 1355</span> <span class="comment"> F. James Rohlf, Hierarchical clustering using the minimum spanning tree,</span></div><div class="line"><a name="l01356"></a><span class="lineno"> 1356</span> <span class="comment"> The Computer Journal, vol. 16, 1973, p. 93–95.</span></div><div class="line"><a name="l01357"></a><span class="lineno"> 1357</span> <span class="comment">*/</span></div><div class="line"><a name="l01358"></a><span class="lineno"> 1358</span>  t_index i;</div><div class="line"><a name="l01359"></a><span class="lineno"> 1359</span>  t_index idx2;</div><div class="line"><a name="l01360"></a><span class="lineno"> 1360</span>  doubly_linked_list active_nodes(N);</div><div class="line"><a name="l01361"></a><span class="lineno"> 1361</span>  auto_array_ptr<t_float> d(N);</div><div class="line"><a name="l01362"></a><span class="lineno"> 1362</span> </div><div class="line"><a name="l01363"></a><span class="lineno"> 1363</span>  t_index prev_node;</div><div class="line"><a name="l01364"></a><span class="lineno"> 1364</span>  t_float min;</div><div class="line"><a name="l01365"></a><span class="lineno"> 1365</span> </div><div class="line"><a name="l01366"></a><span class="lineno"> 1366</span>  <span class="comment">// first iteration</span></div><div class="line"><a name="l01367"></a><span class="lineno"> 1367</span>  idx2 = 1;</div><div class="line"><a name="l01368"></a><span class="lineno"> 1368</span>  min = std::numeric_limits<t_float>::infinity();</div><div class="line"><a name="l01369"></a><span class="lineno"> 1369</span>  <span class="keywordflow">for</span> (i=1; i<N; ++i) {</div><div class="line"><a name="l01370"></a><span class="lineno"> 1370</span>  d[i] = dist(0,i);</div><div class="line"><a name="l01371"></a><span class="lineno"> 1371</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l01372"></a><span class="lineno"> 1372</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l01373"></a><span class="lineno"> 1373</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l01374"></a><span class="lineno"> 1374</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l01375"></a><span class="lineno"> 1375</span>  <span class="keywordflow">if</span> (d[i] < min) {</div><div class="line"><a name="l01376"></a><span class="lineno"> 1376</span>  min = d[i];</div><div class="line"><a name="l01377"></a><span class="lineno"> 1377</span>  idx2 = i;</div><div class="line"><a name="l01378"></a><span class="lineno"> 1378</span>  }</div><div class="line"><a name="l01379"></a><span class="lineno"> 1379</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(d[i]))</div><div class="line"><a name="l01380"></a><span class="lineno"> 1380</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l01381"></a><span class="lineno"> 1381</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l01382"></a><span class="lineno"> 1382</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l01383"></a><span class="lineno"> 1383</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l01384"></a><span class="lineno"> 1384</span>  }</div><div class="line"><a name="l01385"></a><span class="lineno"> 1385</span> </div><div class="line"><a name="l01386"></a><span class="lineno"> 1386</span>  Z2.append(0, idx2, min);</div><div class="line"><a name="l01387"></a><span class="lineno"> 1387</span> </div><div class="line"><a name="l01388"></a><span class="lineno"> 1388</span>  <span class="keywordflow">for</span> (t_index j=1; j<N-1; ++j) {</div><div class="line"><a name="l01389"></a><span class="lineno"> 1389</span>  prev_node = idx2;</div><div class="line"><a name="l01390"></a><span class="lineno"> 1390</span>  active_nodes.remove(prev_node);</div><div class="line"><a name="l01391"></a><span class="lineno"> 1391</span> </div><div class="line"><a name="l01392"></a><span class="lineno"> 1392</span>  idx2 = active_nodes.succ[0];</div><div class="line"><a name="l01393"></a><span class="lineno"> 1393</span>  min = d[idx2];</div><div class="line"><a name="l01394"></a><span class="lineno"> 1394</span> </div><div class="line"><a name="l01395"></a><span class="lineno"> 1395</span>  <span class="keywordflow">for</span> (i=idx2; i<N; i=active_nodes.succ[i]) {</div><div class="line"><a name="l01396"></a><span class="lineno"> 1396</span>  t_float tmp = dist(i, prev_node);</div><div class="line"><a name="l01397"></a><span class="lineno"> 1397</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l01398"></a><span class="lineno"> 1398</span> <span class="preprocessor">#pragma GCC diagnostic push</span></div><div class="line"><a name="l01399"></a><span class="lineno"> 1399</span> <span class="preprocessor">#pragma GCC diagnostic ignored "-Wfloat-equal"</span></div><div class="line"><a name="l01400"></a><span class="lineno"> 1400</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l01401"></a><span class="lineno"> 1401</span>  <span class="keywordflow">if</span> (d[i] > tmp)</div><div class="line"><a name="l01402"></a><span class="lineno"> 1402</span>  d[i] = tmp;</div><div class="line"><a name="l01403"></a><span class="lineno"> 1403</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a>(tmp))</div><div class="line"><a name="l01404"></a><span class="lineno"> 1404</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: nan error"</span>);</div><div class="line"><a name="l01405"></a><span class="lineno"> 1405</span> <span class="preprocessor">#if HAVE_DIAGNOSTIC</span></div><div class="line"><a name="l01406"></a><span class="lineno"> 1406</span> <span class="preprocessor">#pragma GCC diagnostic pop</span></div><div class="line"><a name="l01407"></a><span class="lineno"> 1407</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l01408"></a><span class="lineno"> 1408</span>  <span class="keywordflow">if</span> (d[i] < min) {</div><div class="line"><a name="l01409"></a><span class="lineno"> 1409</span>  min = d[i];</div><div class="line"><a name="l01410"></a><span class="lineno"> 1410</span>  idx2 = i;</div><div class="line"><a name="l01411"></a><span class="lineno"> 1411</span>  }</div><div class="line"><a name="l01412"></a><span class="lineno"> 1412</span>  }</div><div class="line"><a name="l01413"></a><span class="lineno"> 1413</span>  Z2.append(prev_node, idx2, min);</div><div class="line"><a name="l01414"></a><span class="lineno"> 1414</span>  }</div><div class="line"><a name="l01415"></a><span class="lineno"> 1415</span> }</div><div class="line"><a name="l01416"></a><span class="lineno"> 1416</span> </div><div class="line"><a name="l01417"></a><span class="lineno"> 1417</span> <span class="keyword">template</span> <method_codes_vector method, <span class="keyword">typename</span> t_dissimilarity></div><div class="line"><a name="l01418"></a><span class="lineno"> 1418</span> <span class="keyword">static</span> <span class="keywordtype">void</span> generic_linkage_vector(<span class="keyword">const</span> t_index N,</div><div class="line"><a name="l01419"></a><span class="lineno"> 1419</span>  t_dissimilarity & dist,</div><div class="line"><a name="l01420"></a><span class="lineno"> 1420</span>  cluster_result & Z2) {</div><div class="line"><a name="l01421"></a><span class="lineno"> 1421</span>  <span class="comment">/*</span></div><div class="line"><a name="l01422"></a><span class="lineno"> 1422</span> <span class="comment"> N: integer, number of data points</span></div><div class="line"><a name="l01423"></a><span class="lineno"> 1423</span> <span class="comment"> dist: function pointer to the metric</span></div><div class="line"><a name="l01424"></a><span class="lineno"> 1424</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l01425"></a><span class="lineno"> 1425</span> <span class="comment"></span></div><div class="line"><a name="l01426"></a><span class="lineno"> 1426</span> <span class="comment"> This algorithm is valid for the distance update methods</span></div><div class="line"><a name="l01427"></a><span class="lineno"> 1427</span> <span class="comment"> "Ward", "centroid" and "median" only!</span></div><div class="line"><a name="l01428"></a><span class="lineno"> 1428</span> <span class="comment"> */</span></div><div class="line"><a name="l01429"></a><span class="lineno"> 1429</span>  <span class="keyword">const</span> t_index N_1 = N-1;</div><div class="line"><a name="l01430"></a><span class="lineno"> 1430</span>  t_index i, j; <span class="comment">// loop variables</span></div><div class="line"><a name="l01431"></a><span class="lineno"> 1431</span>  t_index idx1, idx2; <span class="comment">// row and column indices</span></div><div class="line"><a name="l01432"></a><span class="lineno"> 1432</span> </div><div class="line"><a name="l01433"></a><span class="lineno"> 1433</span>  auto_array_ptr<t_index> n_nghbr(N_1); <span class="comment">// array of nearest neighbors</span></div><div class="line"><a name="l01434"></a><span class="lineno"> 1434</span>  auto_array_ptr<t_float> mindist(N_1); <span class="comment">// distances to the nearest neighbors</span></div><div class="line"><a name="l01435"></a><span class="lineno"> 1435</span>  auto_array_ptr<t_index> row_repr(N); <span class="comment">// row_repr[i]: node number that the</span></div><div class="line"><a name="l01436"></a><span class="lineno"> 1436</span>  <span class="comment">// i-th row represents</span></div><div class="line"><a name="l01437"></a><span class="lineno"> 1437</span>  doubly_linked_list active_nodes(N);</div><div class="line"><a name="l01438"></a><span class="lineno"> 1438</span>  binary_min_heap nn_distances(&*mindist, N_1); <span class="comment">// minimum heap structure for</span></div><div class="line"><a name="l01439"></a><span class="lineno"> 1439</span>  <span class="comment">// the distance to the nearest neighbor of each point</span></div><div class="line"><a name="l01440"></a><span class="lineno"> 1440</span>  t_index node1, node2; <span class="comment">// node numbers in the output</span></div><div class="line"><a name="l01441"></a><span class="lineno"> 1441</span>  t_float min; <span class="comment">// minimum and row index for nearest-neighbor search</span></div><div class="line"><a name="l01442"></a><span class="lineno"> 1442</span> </div><div class="line"><a name="l01443"></a><span class="lineno"> 1443</span>  <span class="keywordflow">for</span> (i=0; i<N; ++i)</div><div class="line"><a name="l01444"></a><span class="lineno"> 1444</span>  <span class="comment">// Build a list of row ↔ node label assignments.</span></div><div class="line"><a name="l01445"></a><span class="lineno"> 1445</span>  <span class="comment">// Initially i ↦ i</span></div><div class="line"><a name="l01446"></a><span class="lineno"> 1446</span>  row_repr[i] = i;</div><div class="line"><a name="l01447"></a><span class="lineno"> 1447</span> </div><div class="line"><a name="l01448"></a><span class="lineno"> 1448</span>  <span class="comment">// Initialize the minimal distances:</span></div><div class="line"><a name="l01449"></a><span class="lineno"> 1449</span>  <span class="comment">// Find the nearest neighbor of each point.</span></div><div class="line"><a name="l01450"></a><span class="lineno"> 1450</span>  <span class="comment">// n_nghbr[i] = argmin_{j>i} D(i,j) for i in range(N-1)</span></div><div class="line"><a name="l01451"></a><span class="lineno"> 1451</span>  <span class="keywordflow">for</span> (i=0; i<N_1; ++i) {</div><div class="line"><a name="l01452"></a><span class="lineno"> 1452</span>  min = std::numeric_limits<t_float>::infinity();</div><div class="line"><a name="l01453"></a><span class="lineno"> 1453</span>  t_index idx;</div><div class="line"><a name="l01454"></a><span class="lineno"> 1454</span>  <span class="keywordflow">for</span> (idx=j=i+1; j<N; ++j) {</div><div class="line"><a name="l01455"></a><span class="lineno"> 1455</span>  t_float tmp;</div><div class="line"><a name="l01456"></a><span class="lineno"> 1456</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01457"></a><span class="lineno"> 1457</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01458"></a><span class="lineno"> 1458</span>  tmp = dist.ward_initial(i,j);</div><div class="line"><a name="l01459"></a><span class="lineno"> 1459</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01460"></a><span class="lineno"> 1460</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01461"></a><span class="lineno"> 1461</span>  tmp = dist.template sqeuclidean<true>(i,j);</div><div class="line"><a name="l01462"></a><span class="lineno"> 1462</span>  }</div><div class="line"><a name="l01463"></a><span class="lineno"> 1463</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01464"></a><span class="lineno"> 1464</span>  min = tmp;</div><div class="line"><a name="l01465"></a><span class="lineno"> 1465</span>  idx = j;</div><div class="line"><a name="l01466"></a><span class="lineno"> 1466</span>  }</div><div class="line"><a name="l01467"></a><span class="lineno"> 1467</span>  }</div><div class="line"><a name="l01468"></a><span class="lineno"> 1468</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01469"></a><span class="lineno"> 1469</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01470"></a><span class="lineno"> 1470</span>  mindist[i] = t_dissimilarity::ward_initial_conversion(min);</div><div class="line"><a name="l01471"></a><span class="lineno"> 1471</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01472"></a><span class="lineno"> 1472</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01473"></a><span class="lineno"> 1473</span>  mindist[i] = min;</div><div class="line"><a name="l01474"></a><span class="lineno"> 1474</span>  }</div><div class="line"><a name="l01475"></a><span class="lineno"> 1475</span>  n_nghbr[i] = idx;</div><div class="line"><a name="l01476"></a><span class="lineno"> 1476</span>  }</div><div class="line"><a name="l01477"></a><span class="lineno"> 1477</span> </div><div class="line"><a name="l01478"></a><span class="lineno"> 1478</span>  <span class="comment">// Put the minimal distances into a heap structure to make the repeated</span></div><div class="line"><a name="l01479"></a><span class="lineno"> 1479</span>  <span class="comment">// global minimum searches fast.</span></div><div class="line"><a name="l01480"></a><span class="lineno"> 1480</span>  nn_distances.heapify();</div><div class="line"><a name="l01481"></a><span class="lineno"> 1481</span> </div><div class="line"><a name="l01482"></a><span class="lineno"> 1482</span>  <span class="comment">// Main loop: We have N-1 merging steps.</span></div><div class="line"><a name="l01483"></a><span class="lineno"> 1483</span>  <span class="keywordflow">for</span> (i=0; i<N_1; ++i) {</div><div class="line"><a name="l01484"></a><span class="lineno"> 1484</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01485"></a><span class="lineno"> 1485</span> </div><div class="line"><a name="l01486"></a><span class="lineno"> 1486</span>  <span class="keywordflow">while</span> ( active_nodes.is_inactive(n_nghbr[idx1]) ) {</div><div class="line"><a name="l01487"></a><span class="lineno"> 1487</span>  <span class="comment">// Recompute the minimum mindist[idx1] and n_nghbr[idx1].</span></div><div class="line"><a name="l01488"></a><span class="lineno"> 1488</span>  n_nghbr[idx1] = j = active_nodes.succ[idx1]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01489"></a><span class="lineno"> 1489</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01490"></a><span class="lineno"> 1490</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01491"></a><span class="lineno"> 1491</span>  min = dist.ward(idx1,j);</div><div class="line"><a name="l01492"></a><span class="lineno"> 1492</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01493"></a><span class="lineno"> 1493</span>  t_float <span class="keyword">const</span> tmp = dist.ward(idx1,j);</div><div class="line"><a name="l01494"></a><span class="lineno"> 1494</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01495"></a><span class="lineno"> 1495</span>  min = tmp;</div><div class="line"><a name="l01496"></a><span class="lineno"> 1496</span>  n_nghbr[idx1] = j;</div><div class="line"><a name="l01497"></a><span class="lineno"> 1497</span>  }</div><div class="line"><a name="l01498"></a><span class="lineno"> 1498</span>  }</div><div class="line"><a name="l01499"></a><span class="lineno"> 1499</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01500"></a><span class="lineno"> 1500</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01501"></a><span class="lineno"> 1501</span>  min = dist.template sqeuclidean<true>(idx1,j);</div><div class="line"><a name="l01502"></a><span class="lineno"> 1502</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01503"></a><span class="lineno"> 1503</span>  t_float <span class="keyword">const</span> tmp = dist.template sqeuclidean<true>(idx1,j);</div><div class="line"><a name="l01504"></a><span class="lineno"> 1504</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01505"></a><span class="lineno"> 1505</span>  min = tmp;</div><div class="line"><a name="l01506"></a><span class="lineno"> 1506</span>  n_nghbr[idx1] = j;</div><div class="line"><a name="l01507"></a><span class="lineno"> 1507</span>  }</div><div class="line"><a name="l01508"></a><span class="lineno"> 1508</span>  }</div><div class="line"><a name="l01509"></a><span class="lineno"> 1509</span>  }</div><div class="line"><a name="l01510"></a><span class="lineno"> 1510</span>  <span class="comment">/* Update the heap with the new true minimum and search for the (possibly</span></div><div class="line"><a name="l01511"></a><span class="lineno"> 1511</span> <span class="comment"> different) minimal entry. */</span></div><div class="line"><a name="l01512"></a><span class="lineno"> 1512</span>  nn_distances.update_geq(idx1, min);</div><div class="line"><a name="l01513"></a><span class="lineno"> 1513</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01514"></a><span class="lineno"> 1514</span>  }</div><div class="line"><a name="l01515"></a><span class="lineno"> 1515</span> </div><div class="line"><a name="l01516"></a><span class="lineno"> 1516</span>  nn_distances.heap_pop(); <span class="comment">// Remove the current minimum from the heap.</span></div><div class="line"><a name="l01517"></a><span class="lineno"> 1517</span>  idx2 = n_nghbr[idx1];</div><div class="line"><a name="l01518"></a><span class="lineno"> 1518</span> </div><div class="line"><a name="l01519"></a><span class="lineno"> 1519</span>  <span class="comment">// Write the newly found minimal pair of nodes to the output array.</span></div><div class="line"><a name="l01520"></a><span class="lineno"> 1520</span>  node1 = row_repr[idx1];</div><div class="line"><a name="l01521"></a><span class="lineno"> 1521</span>  node2 = row_repr[idx2];</div><div class="line"><a name="l01522"></a><span class="lineno"> 1522</span> </div><div class="line"><a name="l01523"></a><span class="lineno"> 1523</span>  Z2.append(node1, node2, mindist[idx1]);</div><div class="line"><a name="l01524"></a><span class="lineno"> 1524</span> </div><div class="line"><a name="l01525"></a><span class="lineno"> 1525</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01526"></a><span class="lineno"> 1526</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01527"></a><span class="lineno"> 1527</span>  <span class="keywordflow">case</span> METHOD_VECTOR_CENTROID:</div><div class="line"><a name="l01528"></a><span class="lineno"> 1528</span>  dist.merge_inplace(idx1, idx2);</div><div class="line"><a name="l01529"></a><span class="lineno"> 1529</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01530"></a><span class="lineno"> 1530</span>  <span class="keywordflow">case</span> METHOD_VECTOR_MEDIAN:</div><div class="line"><a name="l01531"></a><span class="lineno"> 1531</span>  dist.merge_inplace_weighted(idx1, idx2);</div><div class="line"><a name="l01532"></a><span class="lineno"> 1532</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01533"></a><span class="lineno"> 1533</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01534"></a><span class="lineno"> 1534</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: invalid method"</span>);</div><div class="line"><a name="l01535"></a><span class="lineno"> 1535</span>  }</div><div class="line"><a name="l01536"></a><span class="lineno"> 1536</span> </div><div class="line"><a name="l01537"></a><span class="lineno"> 1537</span>  <span class="comment">// Index idx2 now represents the new (merged) node with label N+i.</span></div><div class="line"><a name="l01538"></a><span class="lineno"> 1538</span>  row_repr[idx2] = N+i;</div><div class="line"><a name="l01539"></a><span class="lineno"> 1539</span>  <span class="comment">// Remove idx1 from the list of active indices (active_nodes).</span></div><div class="line"><a name="l01540"></a><span class="lineno"> 1540</span>  active_nodes.remove(idx1); <span class="comment">// TBD later!!!</span></div><div class="line"><a name="l01541"></a><span class="lineno"> 1541</span> </div><div class="line"><a name="l01542"></a><span class="lineno"> 1542</span>  <span class="comment">// Update the distance matrix</span></div><div class="line"><a name="l01543"></a><span class="lineno"> 1543</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01544"></a><span class="lineno"> 1544</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01545"></a><span class="lineno"> 1545</span>  <span class="comment">/*</span></div><div class="line"><a name="l01546"></a><span class="lineno"> 1546</span> <span class="comment"> Ward linkage.</span></div><div class="line"><a name="l01547"></a><span class="lineno"> 1547</span> <span class="comment"></span></div><div class="line"><a name="l01548"></a><span class="lineno"> 1548</span> <span class="comment"> Shorter and longer distances can occur, not smaller than min(d1,d2)</span></div><div class="line"><a name="l01549"></a><span class="lineno"> 1549</span> <span class="comment"> but maybe bigger than max(d1,d2).</span></div><div class="line"><a name="l01550"></a><span class="lineno"> 1550</span> <span class="comment"> */</span></div><div class="line"><a name="l01551"></a><span class="lineno"> 1551</span>  <span class="comment">// Update the distance matrix in the range [start, idx1).</span></div><div class="line"><a name="l01552"></a><span class="lineno"> 1552</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01553"></a><span class="lineno"> 1553</span>  <span class="keywordflow">if</span> (n_nghbr[j] == idx2) {</div><div class="line"><a name="l01554"></a><span class="lineno"> 1554</span>  n_nghbr[j] = idx1; <span class="comment">// invalidate</span></div><div class="line"><a name="l01555"></a><span class="lineno"> 1555</span>  }</div><div class="line"><a name="l01556"></a><span class="lineno"> 1556</span>  }</div><div class="line"><a name="l01557"></a><span class="lineno"> 1557</span>  <span class="comment">// Update the distance matrix in the range (idx1, idx2).</span></div><div class="line"><a name="l01558"></a><span class="lineno"> 1558</span>  <span class="keywordflow">for</span> ( ; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01559"></a><span class="lineno"> 1559</span>  t_float <span class="keyword">const</span> tmp = dist.ward(j, idx2);</div><div class="line"><a name="l01560"></a><span class="lineno"> 1560</span>  <span class="keywordflow">if</span> (tmp < mindist[j]) {</div><div class="line"><a name="l01561"></a><span class="lineno"> 1561</span>  nn_distances.update_leq(j, tmp);</div><div class="line"><a name="l01562"></a><span class="lineno"> 1562</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01563"></a><span class="lineno"> 1563</span>  }</div><div class="line"><a name="l01564"></a><span class="lineno"> 1564</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n_nghbr[j]==idx2) {</div><div class="line"><a name="l01565"></a><span class="lineno"> 1565</span>  n_nghbr[j] = idx1; <span class="comment">// invalidate</span></div><div class="line"><a name="l01566"></a><span class="lineno"> 1566</span>  }</div><div class="line"><a name="l01567"></a><span class="lineno"> 1567</span>  }</div><div class="line"><a name="l01568"></a><span class="lineno"> 1568</span>  <span class="comment">// Find the nearest neighbor for idx2.</span></div><div class="line"><a name="l01569"></a><span class="lineno"> 1569</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01570"></a><span class="lineno"> 1570</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01571"></a><span class="lineno"> 1571</span>  min = dist.ward(idx2,j);</div><div class="line"><a name="l01572"></a><span class="lineno"> 1572</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01573"></a><span class="lineno"> 1573</span>  t_float <span class="keyword">const</span> tmp = dist.ward(idx2,j);</div><div class="line"><a name="l01574"></a><span class="lineno"> 1574</span>  <span class="keywordflow">if</span> (tmp < min) {</div><div class="line"><a name="l01575"></a><span class="lineno"> 1575</span>  min = tmp;</div><div class="line"><a name="l01576"></a><span class="lineno"> 1576</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01577"></a><span class="lineno"> 1577</span>  }</div><div class="line"><a name="l01578"></a><span class="lineno"> 1578</span>  }</div><div class="line"><a name="l01579"></a><span class="lineno"> 1579</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01580"></a><span class="lineno"> 1580</span>  }</div><div class="line"><a name="l01581"></a><span class="lineno"> 1581</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01582"></a><span class="lineno"> 1582</span> </div><div class="line"><a name="l01583"></a><span class="lineno"> 1583</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01584"></a><span class="lineno"> 1584</span>  <span class="comment">/*</span></div><div class="line"><a name="l01585"></a><span class="lineno"> 1585</span> <span class="comment"> Centroid and median linkage.</span></div><div class="line"><a name="l01586"></a><span class="lineno"> 1586</span> <span class="comment"></span></div><div class="line"><a name="l01587"></a><span class="lineno"> 1587</span> <span class="comment"> Shorter and longer distances can occur, not bigger than max(d1,d2)</span></div><div class="line"><a name="l01588"></a><span class="lineno"> 1588</span> <span class="comment"> but maybe smaller than min(d1,d2).</span></div><div class="line"><a name="l01589"></a><span class="lineno"> 1589</span> <span class="comment"> */</span></div><div class="line"><a name="l01590"></a><span class="lineno"> 1590</span>  <span class="keywordflow">for</span> (j=active_nodes.start; j<idx2; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01591"></a><span class="lineno"> 1591</span>  t_float <span class="keyword">const</span> tmp = dist.template sqeuclidean<true>(j, idx2);</div><div class="line"><a name="l01592"></a><span class="lineno"> 1592</span>  <span class="keywordflow">if</span> (tmp < mindist[j]) {</div><div class="line"><a name="l01593"></a><span class="lineno"> 1593</span>  nn_distances.update_leq(j, tmp);</div><div class="line"><a name="l01594"></a><span class="lineno"> 1594</span>  n_nghbr[j] = idx2;</div><div class="line"><a name="l01595"></a><span class="lineno"> 1595</span>  }</div><div class="line"><a name="l01596"></a><span class="lineno"> 1596</span>  <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n_nghbr[j] == idx2)</div><div class="line"><a name="l01597"></a><span class="lineno"> 1597</span>  n_nghbr[j] = idx1; <span class="comment">// invalidate</span></div><div class="line"><a name="l01598"></a><span class="lineno"> 1598</span>  }</div><div class="line"><a name="l01599"></a><span class="lineno"> 1599</span>  <span class="comment">// Find the nearest neighbor for idx2.</span></div><div class="line"><a name="l01600"></a><span class="lineno"> 1600</span>  <span class="keywordflow">if</span> (idx2<N_1) {</div><div class="line"><a name="l01601"></a><span class="lineno"> 1601</span>  n_nghbr[idx2] = j = active_nodes.succ[idx2]; <span class="comment">// exists, maximally N-1</span></div><div class="line"><a name="l01602"></a><span class="lineno"> 1602</span>  min = dist.template sqeuclidean<true>(idx2,j);</div><div class="line"><a name="l01603"></a><span class="lineno"> 1603</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<N; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01604"></a><span class="lineno"> 1604</span>  t_float <span class="keyword">const</span> tmp = dist.template sqeuclidean<true>(idx2, j);</div><div class="line"><a name="l01605"></a><span class="lineno"> 1605</span>  <span class="keywordflow">if</span> (tmp < min) {</div><div class="line"><a name="l01606"></a><span class="lineno"> 1606</span>  min = tmp;</div><div class="line"><a name="l01607"></a><span class="lineno"> 1607</span>  n_nghbr[idx2] = j;</div><div class="line"><a name="l01608"></a><span class="lineno"> 1608</span>  }</div><div class="line"><a name="l01609"></a><span class="lineno"> 1609</span>  }</div><div class="line"><a name="l01610"></a><span class="lineno"> 1610</span>  nn_distances.update(idx2, min);</div><div class="line"><a name="l01611"></a><span class="lineno"> 1611</span>  }</div><div class="line"><a name="l01612"></a><span class="lineno"> 1612</span>  }</div><div class="line"><a name="l01613"></a><span class="lineno"> 1613</span>  }</div><div class="line"><a name="l01614"></a><span class="lineno"> 1614</span> }</div><div class="line"><a name="l01615"></a><span class="lineno"> 1615</span> </div><div class="line"><a name="l01616"></a><span class="lineno"> 1616</span> <span class="keyword">template</span> <method_codes_vector method, <span class="keyword">typename</span> t_dissimilarity></div><div class="line"><a name="l01617"></a><span class="lineno"> 1617</span> <span class="keyword">static</span> <span class="keywordtype">void</span> generic_linkage_vector_alternative(<span class="keyword">const</span> t_index N,</div><div class="line"><a name="l01618"></a><span class="lineno"> 1618</span>  t_dissimilarity & dist,</div><div class="line"><a name="l01619"></a><span class="lineno"> 1619</span>  cluster_result & Z2) {</div><div class="line"><a name="l01620"></a><span class="lineno"> 1620</span>  <span class="comment">/*</span></div><div class="line"><a name="l01621"></a><span class="lineno"> 1621</span> <span class="comment"> N: integer, number of data points</span></div><div class="line"><a name="l01622"></a><span class="lineno"> 1622</span> <span class="comment"> dist: function pointer to the metric</span></div><div class="line"><a name="l01623"></a><span class="lineno"> 1623</span> <span class="comment"> Z2: output data structure</span></div><div class="line"><a name="l01624"></a><span class="lineno"> 1624</span> <span class="comment"></span></div><div class="line"><a name="l01625"></a><span class="lineno"> 1625</span> <span class="comment"> This algorithm is valid for the distance update methods</span></div><div class="line"><a name="l01626"></a><span class="lineno"> 1626</span> <span class="comment"> "Ward", "centroid" and "median" only!</span></div><div class="line"><a name="l01627"></a><span class="lineno"> 1627</span> <span class="comment"> */</span></div><div class="line"><a name="l01628"></a><span class="lineno"> 1628</span>  <span class="keyword">const</span> t_index N_1 = N-1;</div><div class="line"><a name="l01629"></a><span class="lineno"> 1629</span>  t_index i, j=0; <span class="comment">// loop variables</span></div><div class="line"><a name="l01630"></a><span class="lineno"> 1630</span>  t_index idx1, idx2; <span class="comment">// row and column indices</span></div><div class="line"><a name="l01631"></a><span class="lineno"> 1631</span> </div><div class="line"><a name="l01632"></a><span class="lineno"> 1632</span>  auto_array_ptr<t_index> n_nghbr(2*N-2); <span class="comment">// array of nearest neighbors</span></div><div class="line"><a name="l01633"></a><span class="lineno"> 1633</span>  auto_array_ptr<t_float> mindist(2*N-2); <span class="comment">// distances to the nearest neighbors</span></div><div class="line"><a name="l01634"></a><span class="lineno"> 1634</span> </div><div class="line"><a name="l01635"></a><span class="lineno"> 1635</span>  doubly_linked_list active_nodes(N+N_1);</div><div class="line"><a name="l01636"></a><span class="lineno"> 1636</span>  binary_min_heap nn_distances(&*mindist, N_1, 2*N-2, 1); <span class="comment">// minimum heap</span></div><div class="line"><a name="l01637"></a><span class="lineno"> 1637</span>  <span class="comment">// structure for the distance to the nearest neighbor of each point</span></div><div class="line"><a name="l01638"></a><span class="lineno"> 1638</span> </div><div class="line"><a name="l01639"></a><span class="lineno"> 1639</span>  t_float min; <span class="comment">// minimum for nearest-neighbor searches</span></div><div class="line"><a name="l01640"></a><span class="lineno"> 1640</span> </div><div class="line"><a name="l01641"></a><span class="lineno"> 1641</span>  <span class="comment">// Initialize the minimal distances:</span></div><div class="line"><a name="l01642"></a><span class="lineno"> 1642</span>  <span class="comment">// Find the nearest neighbor of each point.</span></div><div class="line"><a name="l01643"></a><span class="lineno"> 1643</span>  <span class="comment">// n_nghbr[i] = argmin_{j>i} D(i,j) for i in range(N-1)</span></div><div class="line"><a name="l01644"></a><span class="lineno"> 1644</span>  <span class="keywordflow">for</span> (i=1; i<N; ++i) {</div><div class="line"><a name="l01645"></a><span class="lineno"> 1645</span>  min = std::numeric_limits<t_float>::infinity();</div><div class="line"><a name="l01646"></a><span class="lineno"> 1646</span>  t_index idx;</div><div class="line"><a name="l01647"></a><span class="lineno"> 1647</span>  <span class="keywordflow">for</span> (idx=j=0; j<i; ++j) {</div><div class="line"><a name="l01648"></a><span class="lineno"> 1648</span>  t_float tmp;</div><div class="line"><a name="l01649"></a><span class="lineno"> 1649</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01650"></a><span class="lineno"> 1650</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01651"></a><span class="lineno"> 1651</span>  tmp = dist.ward_initial(i,j);</div><div class="line"><a name="l01652"></a><span class="lineno"> 1652</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01653"></a><span class="lineno"> 1653</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01654"></a><span class="lineno"> 1654</span>  tmp = dist.template sqeuclidean<true>(i,j);</div><div class="line"><a name="l01655"></a><span class="lineno"> 1655</span>  }</div><div class="line"><a name="l01656"></a><span class="lineno"> 1656</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01657"></a><span class="lineno"> 1657</span>  min = tmp;</div><div class="line"><a name="l01658"></a><span class="lineno"> 1658</span>  idx = j;</div><div class="line"><a name="l01659"></a><span class="lineno"> 1659</span>  }</div><div class="line"><a name="l01660"></a><span class="lineno"> 1660</span>  }</div><div class="line"><a name="l01661"></a><span class="lineno"> 1661</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01662"></a><span class="lineno"> 1662</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01663"></a><span class="lineno"> 1663</span>  mindist[i] = t_dissimilarity::ward_initial_conversion(min);</div><div class="line"><a name="l01664"></a><span class="lineno"> 1664</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01665"></a><span class="lineno"> 1665</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01666"></a><span class="lineno"> 1666</span>  mindist[i] = min;</div><div class="line"><a name="l01667"></a><span class="lineno"> 1667</span>  }</div><div class="line"><a name="l01668"></a><span class="lineno"> 1668</span>  n_nghbr[i] = idx;</div><div class="line"><a name="l01669"></a><span class="lineno"> 1669</span>  }</div><div class="line"><a name="l01670"></a><span class="lineno"> 1670</span> </div><div class="line"><a name="l01671"></a><span class="lineno"> 1671</span>  <span class="comment">// Put the minimal distances into a heap structure to make the repeated</span></div><div class="line"><a name="l01672"></a><span class="lineno"> 1672</span>  <span class="comment">// global minimum searches fast.</span></div><div class="line"><a name="l01673"></a><span class="lineno"> 1673</span>  nn_distances.heapify();</div><div class="line"><a name="l01674"></a><span class="lineno"> 1674</span> </div><div class="line"><a name="l01675"></a><span class="lineno"> 1675</span>  <span class="comment">// Main loop: We have N-1 merging steps.</span></div><div class="line"><a name="l01676"></a><span class="lineno"> 1676</span>  <span class="keywordflow">for</span> (i=N; i<N+N_1; ++i) {</div><div class="line"><a name="l01677"></a><span class="lineno"> 1677</span>  <span class="comment">/*</span></div><div class="line"><a name="l01678"></a><span class="lineno"> 1678</span> <span class="comment"> The bookkeeping is different from the "stored matrix approach" algorithm</span></div><div class="line"><a name="l01679"></a><span class="lineno"> 1679</span> <span class="comment"> generic_linkage.</span></div><div class="line"><a name="l01680"></a><span class="lineno"> 1680</span> <span class="comment"></span></div><div class="line"><a name="l01681"></a><span class="lineno"> 1681</span> <span class="comment"> mindist[i] stores a lower bound on the minimum distance of the point i to</span></div><div class="line"><a name="l01682"></a><span class="lineno"> 1682</span> <span class="comment"> all points of *lower* index:</span></div><div class="line"><a name="l01683"></a><span class="lineno"> 1683</span> <span class="comment"></span></div><div class="line"><a name="l01684"></a><span class="lineno"> 1684</span> <span class="comment"> mindist[i] ≥ min_{j<i} D(i,j)</span></div><div class="line"><a name="l01685"></a><span class="lineno"> 1685</span> <span class="comment"></span></div><div class="line"><a name="l01686"></a><span class="lineno"> 1686</span> <span class="comment"> Moreover, new nodes do not re-use one of the old indices, but they are</span></div><div class="line"><a name="l01687"></a><span class="lineno"> 1687</span> <span class="comment"> given a new, unique index (SciPy convention: initial nodes are 0,…,N−1,</span></div><div class="line"><a name="l01688"></a><span class="lineno"> 1688</span> <span class="comment"> new nodes are N,…,2N−2).</span></div><div class="line"><a name="l01689"></a><span class="lineno"> 1689</span> <span class="comment"></span></div><div class="line"><a name="l01690"></a><span class="lineno"> 1690</span> <span class="comment"> Invalid nearest neighbors are not recognized by the fact that the stored</span></div><div class="line"><a name="l01691"></a><span class="lineno"> 1691</span> <span class="comment"> distance is smaller than the actual distance, but the list active_nodes</span></div><div class="line"><a name="l01692"></a><span class="lineno"> 1692</span> <span class="comment"> maintains a flag whether a node is inactive. If n_nghbr[i] points to an</span></div><div class="line"><a name="l01693"></a><span class="lineno"> 1693</span> <span class="comment"> active node, the entries nn_distances[i] and n_nghbr[i] are valid,</span></div><div class="line"><a name="l01694"></a><span class="lineno"> 1694</span> <span class="comment"> otherwise they must be recomputed.</span></div><div class="line"><a name="l01695"></a><span class="lineno"> 1695</span> <span class="comment"> */</span></div><div class="line"><a name="l01696"></a><span class="lineno"> 1696</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01697"></a><span class="lineno"> 1697</span>  <span class="keywordflow">while</span> ( active_nodes.is_inactive(n_nghbr[idx1]) ) {</div><div class="line"><a name="l01698"></a><span class="lineno"> 1698</span>  <span class="comment">// Recompute the minimum mindist[idx1] and n_nghbr[idx1].</span></div><div class="line"><a name="l01699"></a><span class="lineno"> 1699</span>  n_nghbr[idx1] = j = active_nodes.start;</div><div class="line"><a name="l01700"></a><span class="lineno"> 1700</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01701"></a><span class="lineno"> 1701</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01702"></a><span class="lineno"> 1702</span>  min = dist.ward_extended(idx1,j);</div><div class="line"><a name="l01703"></a><span class="lineno"> 1703</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01704"></a><span class="lineno"> 1704</span>  t_float tmp = dist.ward_extended(idx1,j);</div><div class="line"><a name="l01705"></a><span class="lineno"> 1705</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01706"></a><span class="lineno"> 1706</span>  min = tmp;</div><div class="line"><a name="l01707"></a><span class="lineno"> 1707</span>  n_nghbr[idx1] = j;</div><div class="line"><a name="l01708"></a><span class="lineno"> 1708</span>  }</div><div class="line"><a name="l01709"></a><span class="lineno"> 1709</span>  }</div><div class="line"><a name="l01710"></a><span class="lineno"> 1710</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01711"></a><span class="lineno"> 1711</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01712"></a><span class="lineno"> 1712</span>  min = dist.sqeuclidean_extended(idx1,j);</div><div class="line"><a name="l01713"></a><span class="lineno"> 1713</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[j]; j<idx1; j=active_nodes.succ[j]) {</div><div class="line"><a name="l01714"></a><span class="lineno"> 1714</span>  t_float <span class="keyword">const</span> tmp = dist.sqeuclidean_extended(idx1,j);</div><div class="line"><a name="l01715"></a><span class="lineno"> 1715</span>  <span class="keywordflow">if</span> (tmp<min) {</div><div class="line"><a name="l01716"></a><span class="lineno"> 1716</span>  min = tmp;</div><div class="line"><a name="l01717"></a><span class="lineno"> 1717</span>  n_nghbr[idx1] = j;</div><div class="line"><a name="l01718"></a><span class="lineno"> 1718</span>  }</div><div class="line"><a name="l01719"></a><span class="lineno"> 1719</span>  }</div><div class="line"><a name="l01720"></a><span class="lineno"> 1720</span>  }</div><div class="line"><a name="l01721"></a><span class="lineno"> 1721</span>  <span class="comment">/* Update the heap with the new true minimum and search for the (possibly</span></div><div class="line"><a name="l01722"></a><span class="lineno"> 1722</span> <span class="comment"> different) minimal entry. */</span></div><div class="line"><a name="l01723"></a><span class="lineno"> 1723</span>  nn_distances.update_geq(idx1, min);</div><div class="line"><a name="l01724"></a><span class="lineno"> 1724</span>  idx1 = nn_distances.argmin();</div><div class="line"><a name="l01725"></a><span class="lineno"> 1725</span>  }</div><div class="line"><a name="l01726"></a><span class="lineno"> 1726</span> </div><div class="line"><a name="l01727"></a><span class="lineno"> 1727</span>  idx2 = n_nghbr[idx1];</div><div class="line"><a name="l01728"></a><span class="lineno"> 1728</span>  active_nodes.remove(idx1);</div><div class="line"><a name="l01729"></a><span class="lineno"> 1729</span>  active_nodes.remove(idx2);</div><div class="line"><a name="l01730"></a><span class="lineno"> 1730</span> </div><div class="line"><a name="l01731"></a><span class="lineno"> 1731</span>  Z2.append(idx1, idx2, mindist[idx1]);</div><div class="line"><a name="l01732"></a><span class="lineno"> 1732</span> </div><div class="line"><a name="l01733"></a><span class="lineno"> 1733</span>  <span class="keywordflow">if</span> (i<2*N_1) {</div><div class="line"><a name="l01734"></a><span class="lineno"> 1734</span>  <span class="keywordflow">switch</span> (method) {</div><div class="line"><a name="l01735"></a><span class="lineno"> 1735</span>  <span class="keywordflow">case</span> METHOD_VECTOR_WARD:</div><div class="line"><a name="l01736"></a><span class="lineno"> 1736</span>  <span class="keywordflow">case</span> METHOD_VECTOR_CENTROID:</div><div class="line"><a name="l01737"></a><span class="lineno"> 1737</span>  dist.merge(idx1, idx2, i);</div><div class="line"><a name="l01738"></a><span class="lineno"> 1738</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01739"></a><span class="lineno"> 1739</span> </div><div class="line"><a name="l01740"></a><span class="lineno"> 1740</span>  <span class="keywordflow">case</span> METHOD_VECTOR_MEDIAN:</div><div class="line"><a name="l01741"></a><span class="lineno"> 1741</span>  dist.merge_weighted(idx1, idx2, i);</div><div class="line"><a name="l01742"></a><span class="lineno"> 1742</span>  <span class="keywordflow">break</span>;</div><div class="line"><a name="l01743"></a><span class="lineno"> 1743</span> </div><div class="line"><a name="l01744"></a><span class="lineno"> 1744</span>  <span class="keywordflow">default</span>:</div><div class="line"><a name="l01745"></a><span class="lineno"> 1745</span>  <a class="code" href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a>(<span class="keyword">false</span> && <span class="stringliteral">"fastcluster: invalid method"</span>);</div><div class="line"><a name="l01746"></a><span class="lineno"> 1746</span>  }</div><div class="line"><a name="l01747"></a><span class="lineno"> 1747</span> </div><div class="line"><a name="l01748"></a><span class="lineno"> 1748</span>  n_nghbr[i] = active_nodes.start;</div><div class="line"><a name="l01749"></a><span class="lineno"> 1749</span>  <span class="keywordflow">if</span> (method==METHOD_VECTOR_WARD) {</div><div class="line"><a name="l01750"></a><span class="lineno"> 1750</span>  <span class="comment">/*</span></div><div class="line"><a name="l01751"></a><span class="lineno"> 1751</span> <span class="comment"> Ward linkage.</span></div><div class="line"><a name="l01752"></a><span class="lineno"> 1752</span> <span class="comment"></span></div><div class="line"><a name="l01753"></a><span class="lineno"> 1753</span> <span class="comment"> Shorter and longer distances can occur, not smaller than min(d1,d2)</span></div><div class="line"><a name="l01754"></a><span class="lineno"> 1754</span> <span class="comment"> but maybe bigger than max(d1,d2).</span></div><div class="line"><a name="l01755"></a><span class="lineno"> 1755</span> <span class="comment"> */</span></div><div class="line"><a name="l01756"></a><span class="lineno"> 1756</span>  min = dist.ward_extended(active_nodes.start, i);</div><div class="line"><a name="l01757"></a><span class="lineno"> 1757</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[active_nodes.start]; j<i;</div><div class="line"><a name="l01758"></a><span class="lineno"> 1758</span>  j=active_nodes.succ[j]) {</div><div class="line"><a name="l01759"></a><span class="lineno"> 1759</span>  t_float tmp = dist.ward_extended(j, i);</div><div class="line"><a name="l01760"></a><span class="lineno"> 1760</span>  <span class="keywordflow">if</span> (tmp < min) {</div><div class="line"><a name="l01761"></a><span class="lineno"> 1761</span>  min = tmp;</div><div class="line"><a name="l01762"></a><span class="lineno"> 1762</span>  n_nghbr[i] = j;</div><div class="line"><a name="l01763"></a><span class="lineno"> 1763</span>  }</div><div class="line"><a name="l01764"></a><span class="lineno"> 1764</span>  }</div><div class="line"><a name="l01765"></a><span class="lineno"> 1765</span>  }</div><div class="line"><a name="l01766"></a><span class="lineno"> 1766</span>  <span class="keywordflow">else</span> {</div><div class="line"><a name="l01767"></a><span class="lineno"> 1767</span>  <span class="comment">/*</span></div><div class="line"><a name="l01768"></a><span class="lineno"> 1768</span> <span class="comment"> Centroid and median linkage.</span></div><div class="line"><a name="l01769"></a><span class="lineno"> 1769</span> <span class="comment"></span></div><div class="line"><a name="l01770"></a><span class="lineno"> 1770</span> <span class="comment"> Shorter and longer distances can occur, not bigger than max(d1,d2)</span></div><div class="line"><a name="l01771"></a><span class="lineno"> 1771</span> <span class="comment"> but maybe smaller than min(d1,d2).</span></div><div class="line"><a name="l01772"></a><span class="lineno"> 1772</span> <span class="comment"> */</span></div><div class="line"><a name="l01773"></a><span class="lineno"> 1773</span>  min = dist.sqeuclidean_extended(active_nodes.start, i);</div><div class="line"><a name="l01774"></a><span class="lineno"> 1774</span>  <span class="keywordflow">for</span> (j=active_nodes.succ[active_nodes.start]; j<i;</div><div class="line"><a name="l01775"></a><span class="lineno"> 1775</span>  j=active_nodes.succ[j]) {</div><div class="line"><a name="l01776"></a><span class="lineno"> 1776</span>  t_float tmp = dist.sqeuclidean_extended(j, i);</div><div class="line"><a name="l01777"></a><span class="lineno"> 1777</span>  <span class="keywordflow">if</span> (tmp < min) {</div><div class="line"><a name="l01778"></a><span class="lineno"> 1778</span>  min = tmp;</div><div class="line"><a name="l01779"></a><span class="lineno"> 1779</span>  n_nghbr[i] = j;</div><div class="line"><a name="l01780"></a><span class="lineno"> 1780</span>  }</div><div class="line"><a name="l01781"></a><span class="lineno"> 1781</span>  }</div><div class="line"><a name="l01782"></a><span class="lineno"> 1782</span>  }</div><div class="line"><a name="l01783"></a><span class="lineno"> 1783</span>  <span class="keywordflow">if</span> (idx2<active_nodes.start) {</div><div class="line"><a name="l01784"></a><span class="lineno"> 1784</span>  nn_distances.remove(active_nodes.start);</div><div class="line"><a name="l01785"></a><span class="lineno"> 1785</span>  } <span class="keywordflow">else</span> {</div><div class="line"><a name="l01786"></a><span class="lineno"> 1786</span>  nn_distances.remove(idx2);</div><div class="line"><a name="l01787"></a><span class="lineno"> 1787</span>  }</div><div class="line"><a name="l01788"></a><span class="lineno"> 1788</span>  nn_distances.replace(idx1, i, min);</div><div class="line"><a name="l01789"></a><span class="lineno"> 1789</span>  }</div><div class="line"><a name="l01790"></a><span class="lineno"> 1790</span>  }</div><div class="line"><a name="l01791"></a><span class="lineno"> 1791</span> }</div><div class="line"><a name="l01792"></a><span class="lineno"> 1792</span> </div><div class="line"><a name="l01793"></a><span class="lineno"> 1793</span> <span class="preprocessor">#if HAVE_VISIBILITY</span></div><div class="line"><a name="l01794"></a><span class="lineno"> 1794</span> <span class="preprocessor">#pragma GCC visibility pop</span></div><div class="line"><a name="l01795"></a><span class="lineno"> 1795</span> <span class="preprocessor">#endif</span></div><div class="ttc" id="util_8h_html_a07d17d6d5d1074c0969bc5d3c3d1d84a"><div class="ttname"><a href="util_8h.html#a07d17d6d5d1074c0969bc5d3c3d1d84a">assert</a></div><div class="ttdeci">#define assert(ex)</div><div class="ttdef"><b>Definition:</b> <a href="util_8h_source.html#l00141">util.h:141</a></div></div>
|
|
70
|
+
<div class="ttc" id="fastcluster_8cpp_html_a8abcd9d66492e761592578e82ce2cba0"><div class="ttname"><a href="fastcluster_8cpp.html#a8abcd9d66492e761592578e82ce2cba0">fc_isnan</a></div><div class="ttdeci">bool fc_isnan(double x)</div><div class="ttdef"><b>Definition:</b> <a href="fastcluster_8cpp_source.html#l00019">fastcluster.cpp:19</a></div></div>
|
|
71
|
+
<div class="ttc" id="util_8h_html_a3110dcad20c2a6616d360901b94e06a1"><div class="ttname"><a href="util_8h.html#a3110dcad20c2a6616d360901b94e06a1">free</a></div><div class="ttdeci">VOID_OR_INT free(void *)</div></div>
|
|
72
|
+
</div><!-- fragment --></div><!-- contents -->
|
|
73
|
+
<!-- start footer part -->
|
|
74
|
+
<hr class="footer"/><address class="footer"><small>
|
|
75
|
+
Generated by  <a href="http://www.doxygen.org/index.html">
|
|
76
|
+
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
|
77
|
+
</a> 1.8.13
|
|
78
|
+
</small></address>
|
|
79
|
+
</body>
|
|
80
|
+
</html>
|