﻿/*
Conventions:
s_ is a scalar
v_ is a (one-dimensional) vector
rn_ is an n-dimensional array of vectors
f_ is a (reference to a) file
INSTR (in capitals) is an instruction

This program is in SSA form.  Where there are loops, the pattern is:
  v_FooIn := 
  LOOP
    v_FooCurrent := PHI v_FooIn v_FooOut
	...
	v_FooOut := FUNC v_FooCurrent
  NEXT

There are no permutations (for example) in this program, but there are vectors of booleans
There are also no "subscripted variables" - array indexing is achieved via labelling of FETCH and STORE.
The program has 64 statements / instructions

Input file contains:
  r2_AllEvents, a two-dimensional array (of vectors)
  r2_EventList, a two-dimensional array of deterministic values s.t. r2_EventList.Length == r2_AllEvents.Length
*/

v_Regions := FETCH r2_AllEvents.Length f_Input
STORE v_Regions r2_FilteredEvents.Length f_Output
STORE v_Regions r2_EventPositions.Length f_Output
STORE v_Regions r2_EventLookups.Length f_Output
v_ConstantOne := FILL 1   // positioned for maximum efficiency
v_ConstantZero := FILL 0  // rather than minimum interference
LOOP s_Region v_Regions  // shorthand for looping from SMin(v_Regions) to SMax(v_Regions)
  
  v_NumEvents := FETCH r2_AllEvents[s_Region].Length f_Input
  STORE v_NumEvents r1_MatchAdjusters.Length f_Temp  // re-store each time around loop - is this OK?

  v_FilteredLengthIn := FILL 0
  LOOP s_EventIndex v_NumEvents
    v_EventIds := FETCH r2_AllEvents[s_Region][s_EventIndex] f_Input

	v_NumEventsList := FETCH r2_EventList[s_Region].Length f_Input
	v_CumMatchFlagsIn := FILL FALSE
	LOOP s_EventListPosition v_NumEventsList
	  v_CumMatchFlagsCurrent := PHI v_CumMatchFlagsIn v_CumMatchFlagsOut   // NB: SSA form
	  v_CurrentEvent := FETCH r2_EventList[s_Region][s_EventListPosition] f_Input
	  v_MatchFlags := EQ v_EventIds v_CurrentEvent
	  v_CumMatchFlagsOut := OR v_CumMatchFlagsCurrent v_MatchFlags
	NEXT s_EventListPosition

    v_EventIndex := FILL s_EventIndex
    v_BoundsFlags := LEQ v_EventIndex v_NumEvents  // or INBOUNDS v_NumEvents ?
    v_BoundsAndMatchFlags := AND v_BoundsFlags v_CumMatchFlagsOut
	v_Adjuster := IF v_BoundsAndMatchFlags v_ConstantOne v_ConstantZero
    v_FilteredLengthCurrent := PHI v_FilteredLengthIn v_FilteredLengthOut   // NB: SSA form
    v_FilteredLengthOut := ADD v_FilteredLengthCurrent v_Adjuster
	STORE v_Adjuster r1_MatchAdjusters[s_EventIndex] f_Temp

  NEXT s_EventIndex

  STORE v_FilteredLengthOut r2_FilteredEvents[s_Region].Length f_Output
  STORE v_FilteredLengthOut r2_EventPositions[s_Region].Length f_Output
  STORE v_FilteredLengthOut r2_EventLookups[s_Region].Length f_Output

  // Accumulate MatchAdjusters, and where it is 1 write the corresponding event Id into FilteredEvents
  LOOP s_FilteredEventIndex v_FilteredLengthOut
    v_CumMatchIn := FILL 0
	v_FilteredEventIdsIn := FILL NAN
	v_FilteredEventIndex := FILL s_FilteredEventIndex
    LOOP s_EventIndex2 v_NumEvents
	  v_CumMatchCurrent := PHI v_CumMatchIn v_CumMatchOut
	  v_FilteredEventIdsCurrent := PHI v_FilteredEventIdsIn v_FilteredEventIdsOut
      v_EventIds2 := FETCH r2_AllEvents[s_Region][s_EventIndex2] f_Input
      v_Adjuster2 := FETCH r1_MatchAdjusters[s_EventIndex2] f_Temp
	  v_CumMatchOut := ADD v_CumMatchCurrent v_Adjuster2
	  v_MatchFlags2 := EQ v_Adjuster2 v_ConstantOne
	  v_CorrectIndex := EQ v_FilteredEventIndex v_CumMatchOut
	  v_ShouldAssign := AND v_MatchFlags2 v_CorrectIndex
	  v_FilteredEventIdsOut := IF v_ShouldAssign v_EventIds2 v_FilteredEventIdsCurrent
	NEXT s_EventIndex2

	STORE v_FilteredEventIdsOut r2_FilteredEvents[s_Region][s_FilteredEventIndex] f_Output
	
	// Find position of v_FilteredEventIdsOut in r2_EventList[s_Region]
	v_EventPositionsIn := FILL NAN
	v_NumEventsList2 := FETCH r2_EventList[s_Region].Length f_Input
	LOOP s_EventListIndex2 v_NumEventsList2

	  v_EventPositionsCurrent := PHI v_EventPositionsIn v_EventPositionsOut
	  v_EventList2 := FETCH r2_EventList[s_Region][s_EventListIndex2] f_Input
	  v_MatchFlags3 := EQ v_FilteredEventIdsOut v_EventList2
	  v_EventListIndex := FILL s_EventListIndex2
	  v_BoundsFlags2 := LEQ v_EventListIndex v_NumEvents
	  v_ShouldAssign2 := AND v_MatchFlags3 v_BoundsFlags2
	  v_EventPositionsOut := IF v_ShouldAssign2 v_FilteredEventIndex v_EventPositionsCurrent

	NEXT s_EventListIndex2

	STORE v_EventPositionsOut r2_EventPositions[s_Region][s_FilteredEventIndex] f_Output

	v_EventLookups := DIV v_EventPositionsOut v_NumEventsList2
	STORE v_EventLookups r2_EventLookups[s_Region][s_FilteredEventIndex]

  NEXT s_FilteredEventIndex

NEXT s_Region