Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
blob: 68637c9ce1e2547405f64a66f05801abe298ed83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?xml version="1.0"?>
<!--
  Copyright (C) 2017 R-T Specialty, LLC.

  This file is part of tame-core.

  tame-core 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.

  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-->
<package xmlns="http://www.lovullo.com/rater"
         xmlns:c="http://www.lovullo.com/calc"
         xmlns:t="http://www.lovullo.com/rater/apply-template"
         core="true"
         desc="Operations Based on Vector Length">

  <import package="../base" />
  <import package="../numeric/common" export="true" />


  See the respective test specification for examples.


  <section title="Non-empty Vectors">
    \ref{_first-nonempty_} will yield the result of the first toplevel
      expression that is not an empty vector.
    This template yields an empty vector if no non-empty vectors are found.

    <template name="_first-nonempty_"
              desc="Return the first non-empty vector">
      <param name="@values@" desc="List of vectors" />


      <c:let>
        <c:values>
          <!-- avoid having to copy @values@ multiple times -->
          <c:value name="_list" type="float"
                   desc="Result of body expression">
            <c:set>
              <param-copy name="@values@" />
            </c:set>
          </c:value>
        </c:values>


        <c:apply name="_first_nonempty">
          <c:arg name="list">
            <c:value-of name="_list" />
          </c:arg>

          <c:arg name="index">
            <c:const value="0" desc="First element" />
          </c:arg>

          <c:arg name="length">
            <c:length-of>
              <c:value-of name="_list" />
            </c:length-of>
          </c:arg>
        </c:apply>
      </c:let>
    </template>


    Its helper function is \ref{_first_nonempty},
      which recurses through each vector element until a non-empty vector is
        encountered.

    <function name="_first_nonempty"
              desc="Return the first non-empty vector">
      <param name="list" type="float" set="vector"
             desc="List of vectors to process" />

      <param name="index" type="integer"
             desc="Current index (for recursion), decrementing" />
      <param name="length" type="integer"
             desc="Length of list" />


      <c:let>
        <c:values>
          <c:value name="cur_len" type="integer"
                   desc="Length of current vector">
            <c:length-of>
              <c:value-of name="list" index="index" />
            </c:length-of>
          </c:value>
        </c:values>


        <c:cases>
          <!-- if none were found (end of list), return empty vector -->
          <c:case>
            <c:when name="index">
              <c:gte>
                <c:value-of name="length" />
              </c:gte>
            </c:when>

            <c:set />
          </c:case>

          <!-- non-empty vector, return it -->
          <c:case>
            <c:when name="cur_len">
              <c:gt>
                <c:const value="0" desc="Vector length" />
              </c:gt>
            </c:when>

            <c:value-of name="list" index="index" />
          </c:case>

          <!-- vector was empty, keep going (decrement index) -->
          <c:otherwise>
            <c:recurse>
              <c:arg name="index">
                <t:inc>
                  <c:value-of name="index" />
                </t:inc>
              </c:arg>
            </c:recurse>
          </c:otherwise>
        </c:cases>
      </c:let>
    </function>
  </section>
</package>