# HG changeset patch # User Rik # Date 1411922419 25200 # Node ID ac8a49be686fc261934a252659214aabbe38b2d2 # Parent 751d4a76c2214992d072ee672017bc2c39e1f7bc compare_versions.m: Overhaul function. 20% speed improvement. Clearer error messages. Improved BIST. * compare_versions.m: Replace slow function calls to ismember with direct operator tests. Use 'end' keyword rather than length(vector) for clarity. Replace str2num with str2double for speed and safety. Reference variable names from documentation in error messages. Add expected error message to %!error tests. diff -r 751d4a76c221 -r ac8a49be686f scripts/miscellaneous/compare_versions.m --- a/scripts/miscellaneous/compare_versions.m Sat Sep 27 22:39:24 2014 -0700 +++ b/scripts/miscellaneous/compare_versions.m Sun Sep 28 09:40:19 2014 -0700 @@ -80,87 +80,68 @@ ## Make sure that the version numbers are valid. if (! (ischar (v1) && ischar (v2))) - error ("compare_versions: both version numbers must be strings"); + error ("compare_versions: version numbers V1 and V2 must be strings"); elseif (rows (v1) != 1 || rows (v2) != 1) - error ("compare_versions: version numbers must be a single row"); + error ("compare_versions: version numbers V1 and V2 must be a single row"); endif ## check and make sure that the operator is valid if (! ischar (operator)) - error ("compare_versions: OPERATOR must be a character string"); + error ("compare_versions: OPERATOR must be a string"); elseif (numel (operator) > 2) error ("compare_versions: OPERATOR must be 1 or 2 characters long"); endif - ## trim off any character data that is not part of a normal version - ## number - numbers = "0123456789."; + ## trim off any character data that is not part of a normal version number + v1firstchar = find (! (isdigit (v1) | v1 == "."), 1); + v2firstchar = find (! (isdigit (v2) | v2 == "."), 1); - v1firstchar = find (! ismember (v1, numbers), 1); - v2firstchar = find (! ismember (v2, numbers), 1); - if (! isempty (v1firstchar)) - v1c = v1(v1firstchar:length (v1)); - v1nochar = v1(1:v1firstchar-1); - else + if (isempty (v1firstchar)) v1c = ""; v1nochar = v1; + else + v1c = v1(v1firstchar:end); + v1nochar = v1(1:v1firstchar-1); endif - if (! isempty (v2firstchar)) - v2c = v2(v2firstchar:length (v2)); - v2nochar = v2(1:v2firstchar-1); - else + if (isempty (v2firstchar)) v2c = ""; v2nochar = v2; - endif - - v1n = str2num (char (ostrsplit (v1nochar, "."))); - v2n = str2num (char (ostrsplit (v2nochar, "."))); - if ((isempty (v1n) && isempty (v1c)) || (isempty (v2n) && isempty (v2c))) - error ("compare_versions: given version strings are not valid: %s %s", - v1, v2); + else + v2c = v2(v2firstchar:end); + v2nochar = v2(1:v2firstchar-1); endif - ## Assume that any additional elements would be 0 if one is longer - ## than the other. - maxnumlen = max ([length(v1n) length(v2n)]); - if (length (v1n) < maxnumlen) - v1n(length(v1n)+1:maxnumlen) = 0; + v1n = str2double (ostrsplit (v1nochar, ".")'); + if (isnan (v1n)) + v1n = []; endif - if (length (v2n) < maxnumlen) - v2n(length(v2n)+1:maxnumlen) = 0; + v2n = str2double (ostrsplit (v2nochar, ".")'); + if (isnan (v2n)) + v2n = []; endif - ## Assume that any additional character elements would be 0 if one is - ## longer than the other. + if (isempty (v1n) && isempty (v1c)) + error ("compare_versions: version string V1 is not valid: %s", v1); + elseif (isempty (v2n) && isempty (v2c)) + error ("compare_versions: version string V2 is not valid: %s", v2); + endif + + ## Assume any additional elements would be 0 if one is longer than the other. + maxnumlen = max ([length(v1n) length(v2n)]); + v1n(end+1:maxnumlen) = 0; + v2n(end+1:maxnumlen) = 0; + + ## Assume any additional character elements would be 0, + ## if one is longer than the other. maxcharlen = max ([length(v1c), length(v2c)]); - if (length (v1c) < maxcharlen) - v1c(length(v1c)+1:maxcharlen) = "\0"; - endif - if (length (v2c) < maxcharlen) - v2c(length(v2c)+1:maxcharlen) = "\0"; - endif + v1c(end+1:maxcharlen) = "\0"; + v2c(end+1:maxcharlen) = "\0"; ## Determine the operator. - if (any (ismember (operator, "="))) - equal_op = true; - else - equal_op = false; - endif - if (any (ismember (operator, "~!"))) - not_op = true; - else - not_op = false; - endif - if (any (ismember (operator, "<"))) - lt_op = true; - else - lt_op = false; - endif - if (any (ismember (operator, ">"))) - gt_op = true; - else - gt_op = false; - endif + equal_op = any (operator == "="); + not_op = any (operator == "!" | operator == "~"); + lt_op = any (operator == "<"); + gt_op = any (operator == ">"); ## Make sure that we don't have conflicting operators. if (gt_op && lt_op) @@ -168,9 +149,9 @@ elseif ((gt_op || lt_op) && not_op) error ("compare_versions: OPERATOR cannot contain not and greater than or less than symbols"); elseif (strcmp (operator, "=")) - error ("compare_versions: equality OPERATOR is \"==\", not \"=\""); + error ('compare_versions: equality OPERATOR is "==", not "="'); elseif (! (equal_op || not_op || lt_op || gt_op)) - error ("compare_versions: No valid OPERATOR specified"); + error ("compare_versions: no valid OPERATOR specified"); endif ## Compare the versions (making sure that they're the same shape) @@ -180,7 +161,7 @@ ## so that we only need to check for the output being greater than 1 vcmp = -vcmp; endif - firstdiff = find (vcmp != 0, 1); + firstdiff = find (vcmp, 1); if (isempty (firstdiff)) ## They're equal. @@ -242,12 +223,22 @@ %!assert (compare_versions ("0.1", "0.1", "~="), false) %% Test input validation -%!error (compare_versions (0.1, "0.1", "==")) -%!error (compare_versions ("0.1", 0.1, "==")) -%!error (compare_versions (["0";".";"1"], "0.1", "==")) -%!error (compare_versions ("0.1", ["0";".";"1"], "==")) -%!error (compare_versions ("0.1", "0.1", "<>")) -%!error (compare_versions ("0.1", "0.1", "!>")) -%!error (compare_versions ("0.1", "0.1", "=")) -%!error (compare_versions ("0.1", "0.1", "aa")) +%!error compare_versions () +%!error compare_versions (1) +%!error compare_versions (1,2) +%!error compare_versions (1,2,3,4) +%!error compare_versions (0.1, "0.1", "==") +%!error compare_versions ("0.1", 0.1, "==") +%!error compare_versions (["0";".";"1"], "0.1", "==") +%!error compare_versions ("0.1", ["0";".";"1"], "==") +%!error compare_versions ("0.1", "0.1", 1) +%!error compare_versions ("0.1", "0.1", "==>") +%!error compare_versions (".", "0.1", "==") +%!error compare_versions ("0.1", ".", "==") +%!error compare_versions ("0.1", "0.1", "<>") +%!error compare_versions ("0.1", "0.1", "!>") +%!error compare_versions ("0.1", "0.1", "!<") +%!error compare_versions ("0.1", "0.1", "=") +%!error compare_versions ("0.1", "0.1", "aa") +