1616 */
1717#include "postgres.h"
1818
19- #include <float.h>
20- #include <math.h>
2119#include <limits.h>
2220
2321#include "lib/bipartite_match.h"
2422#include "miscadmin.h"
25- #include "utils/builtins.h"
2623
24+ /*
25+ * The distances computed in hk_breadth_search can easily be seen to never
26+ * exceed u_size. Since we restrict u_size to be less than SHRT_MAX, we
27+ * can therefore use SHRT_MAX as the "infinity" distance needed as a marker.
28+ */
29+ #define HK_INFINITY SHRT_MAX
2730
2831static bool hk_breadth_search (BipartiteMatchState * state );
29- static bool hk_depth_search (BipartiteMatchState * state , int u , int depth );
32+ static bool hk_depth_search (BipartiteMatchState * state , int u );
3033
3134/*
3235 * Given the size of U and V, where each is indexed 1..size, and an adjacency
@@ -37,26 +40,29 @@ BipartiteMatch(int u_size, int v_size, short **adjacency)
3740{
3841 BipartiteMatchState * state = palloc (sizeof (BipartiteMatchState ));
3942
40- Assert (u_size < SHRT_MAX );
41- Assert (v_size < SHRT_MAX );
43+ if (u_size < 0 || u_size >= SHRT_MAX ||
44+ v_size < 0 || v_size >= SHRT_MAX )
45+ elog (ERROR , "invalid set size for BipartiteMatch" );
4246
4347 state -> u_size = u_size ;
4448 state -> v_size = v_size ;
45- state -> matching = 0 ;
4649 state -> adjacency = adjacency ;
47- state -> pair_uv = palloc0 ((u_size + 1 ) * sizeof (short ));
48- state -> pair_vu = palloc0 ((v_size + 1 ) * sizeof (short ));
49- state -> distance = palloc ((u_size + 1 ) * sizeof (float ));
50- state -> queue = palloc ((u_size + 2 ) * sizeof (short ));
50+ state -> matching = 0 ;
51+ state -> pair_uv = (short * ) palloc0 ((u_size + 1 ) * sizeof (short ));
52+ state -> pair_vu = (short * ) palloc0 ((v_size + 1 ) * sizeof (short ));
53+ state -> distance = (short * ) palloc ((u_size + 1 ) * sizeof (short ));
54+ state -> queue = (short * ) palloc ((u_size + 2 ) * sizeof (short ));
5155
5256 while (hk_breadth_search (state ))
5357 {
5458 int u ;
5559
56- for (u = 1 ; u <= u_size ; ++ u )
60+ for (u = 1 ; u <= u_size ; u ++ )
61+ {
5762 if (state -> pair_uv [u ] == 0 )
58- if (hk_depth_search (state , u , 1 ))
63+ if (hk_depth_search (state , u ))
5964 state -> matching ++ ;
65+ }
6066
6167 CHECK_FOR_INTERRUPTS (); /* just in case */
6268 }
@@ -79,27 +85,31 @@ BipartiteMatchFree(BipartiteMatchState *state)
7985 pfree (state );
8086}
8187
88+ /*
89+ * Perform the breadth-first search step of H-K matching.
90+ * Returns true if successful.
91+ */
8292static bool
8393hk_breadth_search (BipartiteMatchState * state )
8494{
8595 int usize = state -> u_size ;
8696 short * queue = state -> queue ;
87- float * distance = state -> distance ;
97+ short * distance = state -> distance ;
8898 int qhead = 0 ; /* we never enqueue any node more than once */
8999 int qtail = 0 ; /* so don't have to worry about wrapping */
90100 int u ;
91101
92- distance [0 ] = get_float4_infinity () ;
102+ distance [0 ] = HK_INFINITY ;
93103
94- for (u = 1 ; u <= usize ; ++ u )
104+ for (u = 1 ; u <= usize ; u ++ )
95105 {
96106 if (state -> pair_uv [u ] == 0 )
97107 {
98108 distance [u ] = 0 ;
99109 queue [qhead ++ ] = u ;
100110 }
101111 else
102- distance [u ] = get_float4_infinity () ;
112+ distance [u ] = HK_INFINITY ;
103113 }
104114
105115 while (qtail < qhead )
@@ -111,45 +121,52 @@ hk_breadth_search(BipartiteMatchState *state)
111121 short * u_adj = state -> adjacency [u ];
112122 int i = u_adj ? u_adj [0 ] : 0 ;
113123
114- for (; i > 0 ; -- i )
124+ for (; i > 0 ; i -- )
115125 {
116126 int u_next = state -> pair_vu [u_adj [i ]];
117127
118- if (isinf ( distance [u_next ]) )
128+ if (distance [u_next ] == HK_INFINITY )
119129 {
120130 distance [u_next ] = 1 + distance [u ];
131+ Assert (qhead < usize + 2 );
121132 queue [qhead ++ ] = u_next ;
122- Assert (qhead <= usize + 2 );
123133 }
124134 }
125135 }
126136 }
127137
128- return ! isinf (distance [0 ]);
138+ return (distance [0 ] != HK_INFINITY );
129139}
130140
141+ /*
142+ * Perform the depth-first search step of H-K matching.
143+ * Returns true if successful.
144+ */
131145static bool
132- hk_depth_search (BipartiteMatchState * state , int u , int depth )
146+ hk_depth_search (BipartiteMatchState * state , int u )
133147{
134- float * distance = state -> distance ;
148+ short * distance = state -> distance ;
135149 short * pair_uv = state -> pair_uv ;
136150 short * pair_vu = state -> pair_vu ;
137151 short * u_adj = state -> adjacency [u ];
138152 int i = u_adj ? u_adj [0 ] : 0 ;
153+ short nextdist ;
139154
140155 if (u == 0 )
141156 return true;
157+ if (distance [u ] == HK_INFINITY )
158+ return false;
159+ nextdist = distance [u ] + 1 ;
142160
143- if ((depth % 8 ) == 0 )
144- check_stack_depth ();
161+ check_stack_depth ();
145162
146- for (; i > 0 ; -- i )
163+ for (; i > 0 ; i -- )
147164 {
148165 int v = u_adj [i ];
149166
150- if (distance [pair_vu [v ]] == distance [ u ] + 1 )
167+ if (distance [pair_vu [v ]] == nextdist )
151168 {
152- if (hk_depth_search (state , pair_vu [v ], depth + 1 ))
169+ if (hk_depth_search (state , pair_vu [v ]))
153170 {
154171 pair_vu [v ] = u ;
155172 pair_uv [u ] = v ;
@@ -158,6 +175,6 @@ hk_depth_search(BipartiteMatchState *state, int u, int depth)
158175 }
159176 }
160177
161- distance [u ] = get_float4_infinity () ;
178+ distance [u ] = HK_INFINITY ;
162179 return false;
163180}
0 commit comments