diff libinterp/corefcn/levenshtein.cc @ 20568:fcb792acab9b

Moving ode45, odeset, odeget, and levenshtein from odepkg to core. * libinterp/corefcn/levenshtein.cc: move function from odepkg into core * libinterp/corefcn/module.mk: include levenshtein.cc * scripts/ode: move ode45, odeset, odeget, and all dependencies from odepkg into core * scripts/module.mk: include them * doc/interpreter/diffeq.txi: add documentation for ode45, odeset, odeget * NEWS: announce functions included with this changeset * scripts/help/__unimplemented__.m: removed new functions
author jcorno <jacopo.corno@gmail.com>
date Thu, 24 Sep 2015 12:58:46 +0200
parents
children d746695bf494
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/levenshtein.cc	Thu Sep 24 12:58:46 2015 +0200
@@ -0,0 +1,109 @@
+/*
+
+Copyright (C) 2014 Jacopo Corno
+Copyright (C) 2014 Carlo de Falco
+Copyright (C) 2013 Roberto Porcu
+Copyright (C) 2013 Mattia Penati
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or (at
+your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "defun.h"
+
+#define MIN2(A,B) ((A)<(B)?(A):(B))
+#define MIN3(A,B,C) (MIN2(MIN2((A),(B)),(C)))
+
+DEFUN (levenshtein, args, nargout,
+          "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{d} =} levenshtein (@var{str1}, @var{str2}, [@var{u_bound}])\n \
+@deftypefnx {Loadable Function} {[@var{d}, @var{mat}] =} levenshtein (@var{str1}, @var{str2}, [@var{u_bound}])\n \
+This function file computes the Levenshtein distance between two strings. More details at @url{http://en.wikipedia.org/wiki/Levenshtein_distance}.\n \
+This function can be called with one or two output arguments: @var{d} is the distance between the two strings and @var{mat} is the matrix computed by Levenshtein algorithm.\n \
+The first and the second input arguments, @var{str1} and @var{str2}, are the two strings to be compared. This comparison is case-sensitive.\n \
+The third argument @var{u_bound} is optional and fixes an upper bound for the distance. If the distance is greater than this limit then the function ends and returns a value equal to Inf.\n \
+@seealso{odeset}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+  octave_idx_type ub;
+
+  if (nargin < 2
+      || nargin > 3
+      || nargout > 2)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  if (nargin == 3)
+    ub = args(2).idx_type_value ();
+  else
+    ub = std::numeric_limits<int32_t>::max ();
+
+  Array<char> s1 (args(0).char_array_value ());
+  char *s1_p = s1.fortran_vec ();
+
+  Array<char> s2 (args(1).char_array_value ());
+  char *s2_p = s2.fortran_vec ();
+
+  octave_idx_type
+    s1len = s1.length (),
+    s2len = s2.length (),
+    ii, jj;
+
+  if (! error_state)
+    {
+      Array<octave_idx_type>
+        dist (dim_vector (s1len + 1, s2len + 1), 0);
+
+      for (ii = 1; ii <= s1len; ii++)
+        dist.xelem (ii, 0) = ii;
+
+      for (jj = 1; jj <= s2len; jj++)
+        dist.xelem (0, jj) = jj;
+
+      for (jj = 1; jj <= s2len; jj++)
+        {
+          for (ii = 1; ii <= s1len; ii++)
+            if (s1_p[ii-1] == s2_p[jj-1])
+              dist.xelem (ii, jj) = dist.xelem (ii-1, jj-1);
+            else
+              dist.xelem (ii, jj) =
+                MIN3(dist.xelem (ii-1, jj) + 1,
+                     dist.xelem (ii, jj-1) + 1,
+                     dist.xelem (ii-1, jj-1) + 1);
+
+          if (dist(MIN2(jj, s1len), jj) > ub)
+            {
+              retval(0) = std::numeric_limits<int32_t>::max ();
+              if (nargout == 2)
+                retval(1) = Matrix ();
+              return retval;
+            }
+        }
+      retval(0) = dist.xelem (s1len, s2len);
+      if (nargout == 2)
+        retval(1) = dist;
+    }
+  return retval;
+}