1 /*
2 
3 Copyright (C) 2009-2016   Lukas F. Reichlin
4 
5 This file is part of LTI Syncope.
6 
7 LTI Syncope is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 LTI Syncope is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with LTI Syncope.  If not, see <http://www.gnu.org/licenses/>.
19 
20 First, this function implemented the following Octave function in C++
21 
22 function [mat_idx, opt_idx] = __lti_input_idx__ (varargin)
23 
24   str_idx = find (cellfun (@ischar, varargin));
25 
26   if (isempty (str_idx))
27     mat_idx = 1 : nargin;
28     opt_idx = [];
29   else
30     mat_idx = 1 : str_idx(1)-1;
31     opt_idx = str_idx(1) : nargin;
32   endif
33 
34 endfunction
35 
36 Later on, the C++ function was extended such that
37 it recognizes classes in some cases.  See comment
38 block in the code for details.  I know this looks
39 like a horrible definition for a function, but it
40 is exactly the behavior I need.
41 
42 Author: Lukas Reichlin <lukas.reichlin@gmail.com>
43 Created: October 2015
44 Version: 0.1
45 
46 */
47 
48 
49 #include <octave/oct.h>
50 #include "config.h"
51 
52 // PKG_ADD: autoload ("__lti_input_idx__", "__control_helper_functions__.oct");
53 DEFUN_DLD (__lti_input_idx__, args, ,
54        "-*- texinfo -*-\n\
55 @deftypefn {Loadable Function} {[@var{mat_idx}, @var{opt_idx}, @var{obj_flg}] =} __lti_input_idx__ (@var{args})\n\
56 Return some indices for cell @var{args}.  For internal use only.\n\
57 Read the source code in @code{lti_input_idx.cc} for details.\n\
58 @end deftypefn")
59 {
60   octave_value_list retval;
61   octave_idx_type nargin = args.length ();
62 
63   // first, check whether a cell is passed
64   if (nargin == 1 && args(0).is_defined () && args(0).OV_ISCELL ())
65   {
66     octave_idx_type len = args(0).cell_value().numel();
67     octave_idx_type idx = len;
68     octave_idx_type offset = 0;
69 
70     // if the cell is not empty, look for the first string
71     for (octave_idx_type i = 0; i < len; i++)
72     {
73       if (args(0).cell_value().elem(i).is_string ())
74       {
75         idx = i;
76         break;
77       }
78     }
79 
80     // ** If the element before the first string is an object,
81     //    then this object belongs to the option index.
82     //      ss (d, ltisys, 'key', val)
83     // ** If there is no string at all in cell args(0), check
84     //    whether the last element in args(0) is an object.
85     //    If so, this object also belongs to the option index.
86     //      tf (num, den, ltisys)
87     // ** All other objects (before built-in types (except chars)
88     //    and after strings) are not recognized as objects.
89     //      ss (a, b, ltisys, c, d, 'key', val, 'lti', ltisys)
90     if (len > 0 && idx > 0
91         && args(0).cell_value().elem(idx-1).OV_ISOBJECT ())
92     {
93       offset = 1;
94     }
95 
96     Range mat_idx (1, idx-offset);
97     Range opt_idx (idx+1-offset, len);
98 
99     retval(2) = offset;     // abused as logical in the LTI constructors
100     retval(1) = opt_idx;
101     retval(0) = mat_idx;
102   }
103   else
104   {
105     print_usage ();
106   }
107 
108   return retval;
109 }
110