<TestSet xmlns:geo="http://www.cems.uwe.ac.uk/xmlwiki/geo">
    <testName>Look-up performance tests</testName>
    <description>
        <p>Purpose: Testing various implementations of a lookup table </p>
        <p>Author: Chris Wallace</p>
    </description>
    <epilog>
        
     (for $s in 1 to 200
      for $step in ("A","B","C","D","E","F","G")
      return local:MidiNote(
       &lt;pitch&gt;
        &lt;step&gt;{$step}&lt;/step&gt;
        &lt;octave&gt;5&lt;/octave&gt;
      &lt;/pitch&gt;)
     )[1]
    </epilog>
    <test>
        <task>Null loop</task>
        <code> declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer { 81 } ;
        </code>
        <expected>81</expected>
    </test>
    <test>
        <task>nested if-then-else expression</task>
        <code>
declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $step := $thispitch/step
  let $alter :=
    if (empty($thispitch/alter)) then 0
    else xs:integer($thispitch/alter)
  let $octave := xs:integer($thispitch/octave)
  let $pitchstep :=
    if ($step = "C") then 0
    else if ($step = "D") then 2
    else if ($step = "E") then 4
    else if ($step = "F") then 5
    else if ($step = "G") then 7
    else if ($step = "A") then 9
    else if ($step = "B") then 11
    else 0
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
</code>
        <expected>81</expected>
    </test>
    <test>
        <task>nested if-then-else expression - - sequence used for $alter</task>
        <code>
declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $step := $thispitch/step
  let $alter :=xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $pitchstep :=
    if ($step = "C") then 0
    else if ($step = "D") then 2
    else if ($step = "E") then 4
    else if ($step = "F") then 5
    else if ($step = "G") then 7
    else if ($step = "A") then 9
    else if ($step = "B") then 11
    else 0
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
</code>
        <expected>81</expected>
    </test>
    <test>
        <task>Define table as a sequence of elements</task>
        <code>
declare variable  $noteStep := 
(
   &lt;note name="C" step="0"/&gt;,
   &lt;note name="D"  step="2"/&gt;,
   &lt;note name="E" step="4"/&gt;,
   &lt;note name="F" step="5"/&gt;,
   &lt;note name="G" step="7"/&gt;,
   &lt;note name="A" step="9"/&gt;,
   &lt;note name="B" step="11"/&gt;
);

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $pitchstep := xs:integer($noteStep[@name = $thispitch/step]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
           </code>
        <expected>81</expected>
    </test>
    <test>
        <task>As above but loop invariant removed</task>
        <code>
declare variable  $noteStep := 
(
   &lt;note name="C" step="0"/&gt;,
   &lt;note name="D"  step="2"/&gt;,
   &lt;note name="E" step="4"/&gt;,
   &lt;note name="F" step="5"/&gt;,
   &lt;note name="G" step="7"/&gt;,
   &lt;note name="A" step="9"/&gt;,
   &lt;note name="B" step="11"/&gt;
);

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $name :=  $thispitch/step
  let $pitchstep := xs:integer($noteStep[@name =$name]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;           </code>
        <expected>81</expected>
    </test>
    <test>
        <task>Define table as a nested element</task>
        <code>
 declare variable  $noteStep := 
&lt;steps&gt;
   &lt;note name="C" step="0"/&gt;
   &lt;note name="D"  step="2"/&gt;
   &lt;note name="E" step="4"/&gt;
   &lt;note name="F" step="5"/&gt;
   &lt;note name="G" step="7"/&gt;
   &lt;note name="A" step="9"/&gt;
   &lt;note name="B" step="11"/&gt;
&lt;/steps&gt;;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $pitchstep := xs:integer($noteStep/note[@name = $thispitch/step]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
          </code>
        <expected>81</expected>
    </test>
    <test>
        <task>As above but loop invariant removed</task>
        <code>
declare variable  $noteStep := 
&lt;steps&gt;
   &lt;note name="C" step="0"/&gt;
   &lt;note name="D"  step="2"/&gt;
   &lt;note name="E" step="4"/&gt;
   &lt;note name="F" step="5"/&gt;
   &lt;note name="G" step="7"/&gt;
   &lt;note name="A" step="9"/&gt;
   &lt;note name="B" step="11"/&gt;
&lt;/steps&gt;;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $name := $thispitch/step
  let $pitchstep :=xs:integer($noteStep/note[@name = $name]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
     </code>
        <expected>81</expected>
    </test>
    <test>
        <task>As above but loop invariant removed and no explicit casting</task>
        <code>
declare variable  $noteStep := 
&lt;steps&gt;
   &lt;note name="C" step="0"/&gt;
   &lt;note name="D"  step="2"/&gt;
   &lt;note name="E" step="4"/&gt;
   &lt;note name="F" step="5"/&gt;
   &lt;note name="G" step="7"/&gt;
   &lt;note name="A" step="9"/&gt;
   &lt;note name="B" step="11"/&gt;
&lt;/steps&gt;;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := ($thispitch/alter,0)[1]
  let $octave := $thispitch/octave
  let $name := $thispitch/step
  let $pitchstep :=$noteStep/note[@name = $name]/@step
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
     </code>
        <expected>81</expected>
    </test>
    <test>
        <task>Define table as a nested element </task>
        <code>
 declare variable  $noteStep := 
&lt;steps&gt;
    &lt;note&gt;&lt;name&gt;C&lt;/name&gt;&lt;step&gt;0&lt;/step&gt;&lt;/note&gt; 
    &lt;note&gt;&lt;name&gt;D&lt;/name&gt;&lt;step&gt;2&lt;/step&gt;&lt;/note&gt;  
    &lt;note&gt;&lt;name&gt;E&lt;/name&gt;&lt;step&gt;4&lt;/step&gt;&lt;/note&gt;    
    &lt;note&gt;&lt;name&gt;F&lt;/name&gt;&lt;step&gt;5&lt;/step&gt;&lt;/note&gt;    
    &lt;note&gt;&lt;name&gt;G&lt;/name&gt;&lt;step&gt;7&lt;/step&gt;&lt;/note&gt;    
    &lt;note&gt;&lt;name&gt;A&lt;/name&gt;&lt;step&gt;9&lt;/step&gt;&lt;/note&gt;   
    &lt;note&gt;&lt;name&gt;B&lt;/name&gt;&lt;step&gt;11&lt;/step&gt;&lt;/note&gt;   
&lt;/steps&gt;;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $name := $thispitch/step
  let $pitchstep := xs:integer($noteStep/note[name = $name]/step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;
          </code>
        <expected>81</expected>
    </test>
    <test>
        <task>Define table in database</task>
        <code>
declare variable  $scale := doc("/db/Wiki/Music/notemap.xml")//note;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $pitchstep := xs:integer($scale[@name = $thispitch/step]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;

           </code>
        <expected>81</expected>
    </test>
    <test>
        <task>Define table in database - loop invariant removed</task>
        <code>
declare variable  $scale := doc("/db/Wiki/Music/notemap.xml")//note;

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $name := $thispitch/step
  let $pitchstep := xs:integer($scale[@name = $name]/@step)
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;

           </code>
        <expected>81</expected>
    </test>
    <test>
        <task>Computed from codepoint</task>
        <code>
declare variable  $noteStep :=  (9,11,0,2,4,5,7);

declare function local:MidiNote($thispitch as element(pitch) ) as xs:integer
{
  let $alter := xs:integer(($thispitch/alter,0)[1])
  let $octave := xs:integer($thispitch/octave)
  let $index := string-to-codepoints($thispitch/step) - 64
  let $pitchstep :=xs:integer($noteStep[$index])
  return 12 * ($octave + 1) + $pitchstep + $alter
} ;           </code>
        <expected>81</expected>
    </test>
</TestSet>