78{
79 int m,
80 n;
81 int *prev;
82 int *curr;
83 int *s_char_len = NULL;
87 const char *tend = target + tlen;
88
89
90
91
92
93
94#ifdef LEVENSHTEIN_LESS_EQUAL
95 int start_column,
96 stop_column;
97
98#undef START_COLUMN
99#undef STOP_COLUMN
100#define START_COLUMN start_column
101#define STOP_COLUMN stop_column
102#else
103#undef START_COLUMN
104#undef STOP_COLUMN
105#define START_COLUMN 0
106#define STOP_COLUMN m
107#endif
108
109
112
113
114
115
116
117 if (!m)
118 return n * ins_c;
119 if (!n)
120 return m * del_c;
121
122
123
124
125
126
127
128
129 if (!trusted &&
133 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
134 errmsg(
"levenshtein argument exceeds maximum length of %d characters",
136
137#ifdef LEVENSHTEIN_LESS_EQUAL
138
139 start_column = 0;
140 stop_column = m + 1;
141
142
143
144
145
146
147
148 if (max_d >= 0)
149 {
150 int min_theo_d;
151 int max_theo_d;
152 int net_inserts = n - m;
153
154 min_theo_d = net_inserts < 0 ?
155 -net_inserts * del_c : net_inserts * ins_c;
156 if (min_theo_d > max_d)
157 return max_d + 1;
158 if (ins_c + del_c < sub_c)
159 sub_c = ins_c + del_c;
160 max_theo_d = min_theo_d + sub_c *
Min(m, n);
161 if (max_d >= max_theo_d)
162 max_d = -1;
163 else if (ins_c + del_c > 0)
164 {
165
166
167
168
169
170
171
172
173
174
175
176
177 int slack_d = max_d - min_theo_d;
178 int best_column = net_inserts < 0 ? -net_inserts : 0;
179
180 stop_column = best_column + (slack_d / (ins_c + del_c)) + 1;
181 if (stop_column > m)
182 stop_column = m + 1;
183 }
184 }
185#endif
186
187
188
189
190
191
192
193
194
195 if (m != slen || n != tlen)
196 {
199
200 s_char_len = (
int *)
palloc((m + 1) *
sizeof(int));
201 for (
i = 0;
i < m; ++
i)
202 {
205 }
207 }
208
209
210 ++m;
211 ++n;
212
213
214 prev = (
int *)
palloc(2 * m *
sizeof(
int));
215 curr = prev + m;
216
217
218
219
220
223
224
225 for (
y = target,
j = 1;
j < n;
j++)
226 {
227 int *temp;
231
232#ifdef LEVENSHTEIN_LESS_EQUAL
233
234
235
236
237
238
239
240 if (stop_column < m)
241 {
242 prev[stop_column] = max_d + 1;
243 ++stop_column;
244 }
245
246
247
248
249
250
251
252 if (start_column == 0)
253 {
256 }
257 else
259#else
262#endif
263
264
265
266
267
268
269
270
271 if (s_char_len != NULL)
272 {
274 {
275 int ins;
276 int del;
277 int sub;
278 int x_char_len = s_char_len[
i - 1];
279
280
281
282
283
284
285
286
287
288
289 ins = prev[
i] + ins_c;
290 del = curr[
i - 1] + del_c;
291 if (
x[x_char_len - 1] ==
y[y_char_len - 1]
292 && x_char_len == y_char_len &&
295 else
296 sub = prev[
i - 1] + sub_c;
297
298
299 curr[
i] =
Min(ins, del);
300 curr[
i] =
Min(curr[
i], sub);
301
302
304 }
305 }
306 else
307 {
309 {
310 int ins;
311 int del;
312 int sub;
313
314
315 ins = prev[
i] + ins_c;
316 del = curr[
i - 1] + del_c;
317 sub = prev[
i - 1] + ((*
x == *
y) ? 0 : sub_c);
318
319
320 curr[
i] =
Min(ins, del);
321 curr[
i] =
Min(curr[
i], sub);
322
323
325 }
326 }
327
328
329 temp = curr;
330 curr = prev;
331 prev = temp;
332
333
335
336#ifdef LEVENSHTEIN_LESS_EQUAL
337
338
339
340
341
342
343
344
345 if (max_d >= 0)
346 {
347
348
349
350
351
352
353
354
355 int zp =
j - (n - m);
356
357
358 while (stop_column > 0)
359 {
360 int ii = stop_column - 1;
361 int net_inserts = ii - zp;
362
363 if (prev[ii] + (net_inserts > 0 ? net_inserts * ins_c :
364 -net_inserts * del_c) <= max_d)
365 break;
366 stop_column--;
367 }
368
369
370 while (start_column < stop_column)
371 {
372 int net_inserts = start_column - zp;
373
374 if (prev[start_column] +
375 (net_inserts > 0 ? net_inserts * ins_c :
376 -net_inserts * del_c) <= max_d)
377 break;
378
379
380
381
382
383
384 prev[start_column] = max_d + 1;
385 curr[start_column] = max_d + 1;
386 if (start_column != 0)
387 source += (s_char_len != NULL) ? s_char_len[start_column - 1] : 1;
388 start_column++;
389 }
390
391
392 if (start_column >= stop_column)
393 return max_d + 1;
394 }
395#endif
396 }
397
398
399
400
401
402 return prev[m - 1];
403}
int errcode(int sqlerrcode)
#define ereport(elevel,...)
#define MAX_LEVENSHTEIN_STRLEN
int pg_mbstrlen_with_len(const char *mbstr, int limit)
int pg_mblen_range(const char *mbstr, const char *end)
static rewind_source * source
static bool rest_of_char_same(const char *s1, const char *s2, int len)
#define send(s, buf, len, flags)