!!! matrix of conds: definition conditions as logical formula in 
!!! disjunctive normal form
!!! set : union of intervals (normally disjoint with exo1)
!!! ppset : latex (pretty) printing of set
!!! SETUNION : resolve non disjoint union + sort interval
!!! ALGO : process inegalities first in conjonction (row), make first interval
!!!  then extract inequalities and split latter interval into subintervals


wims_backslash_insmath=yes
wims_backslash_instex=yes
wims_multiexec=pari,octave,maxima

!!! PROCESS USER SET /TO COMPARE WRT GIVEN DEFSET

!if  $user=Fin
!goto SETUNION
!endif

!!!! CREATE SET from CONDITIONS matrix (lesconds) for given fonction 
!!!! (read from var.init)

!if $cnt=0

!!!!!  TRIVIAL CASES
!!!!! emptyset represented by set=empty ; set of reals represented by ]-inf,+inf[
!if $lesconds=FALSE
    set=
    ppset=\emptyset
    !goto ENDSET
!endif
!if $lesconds=TRUE
    set=0,-inf,+inf,0
    ppset=\mathbb{R}
    !goto ENDSET
!endif

!!! ELSE PROCESS CONDITIONS 
rcnt=!rowcnt $lesconds
!if $rcnt=0
    set=
!else
    set=
    !for r=1 to $rcnt
        row= !row $r of $lesconds
        !if FALSE isin $row
            !goto NEXTROW
        !else
            glb=-inf
            lb=0
            lub=+inf
            rb=0
            nonequal= 
!!!! create first interval 
           !for def in $row
                 !if $def=TRUE
                     !goto NEXTDEF
                 !endif
                 rel=!word 1 of $def
                 nb = !word 2 of $def
                 !if $rel=neq
                     nonequal=$nonequal,$nb
                 !endif
                 !if  $rel=geq
!!!!   correction bug : y>nb and y>=nb  donnait y<= nb au lieu de y>nb
!!!!   !if $glb=-inf  or  $[$nb]>=$[$glb]
                      !if $glb=-inf  or  $[$nb]>$[$glb]
                           glb=$nb
                           lb=1 
                      !endif
                 !endif
                 !if  $rel=gt
                      !if $glb=-inf  or  $[$nb]>=$[$glb]
                           glb=$nb
                           lb=0 
                      !endif
                 !endif
                !if  $rel=leq
                      !if $lub=+inf  or  $[$nb]<$[$lub]
                           lub=$nb
                           rb=1 
                      !endif
                 !endif
                 !if  $rel=lt
                      !if $lub=+inf  or  $[$nb]<=$[$lub]
                           lub=$nb
                           rb=0 
                      !endif
                 !endif
!!!!! TEST COHERENCE / break if emptyset
!!!! emptyset si  glb > lub or 0,a,a,0  / 0,a,a,1 /   1,a,a,0
                 left=$[$glb]
                 right=$[$lub]
!!! NB : si int=0,-int,+int,0 on a left=NaN et right=NaN
                !if $left > $right or ($left!=NaN and  $right!=NaN and $left=$right and ($[$lb]=0 or $[$rb]=0))
                      !goto NEXTROW
                 !endif
                 :NEXTDEF
            !next def
            int=$lb,$glb,$lub,$rb  
            union=
!!!!!! split into sub-intervals according to elements in nonequal
            !if $nonequal!=$empty
                nonequal=!nonempty item $nonequal
                nonequal=!sort numeric item $nonequal
                !for elmnt in $nonequal
                     val=$[$elmnt]
                    !if $val=$[$glb] and $[$lb]=1
                        lb=0
                    !endif
                    !if $val=$[$lub] and $[$rb]=1
!!!!!  modif 20 aout 
                         rb=0
                    !endif
                    !if ($glb=-inf or $val>$[$glb]) and ($lub=+inf or $val<$[$lub])
                        union=$union;$lb,$glb,$elmnt,0
                        lb=0
                        glb=$elmnt
                    !endif
!!!! new interval to split with next elmnt
                     int=$lb,$glb,$lub,$rb
                !next elmnt
            !endif
!!!!! end remove nonequal
            union=$union;$int
            union=!row 2 to -1 of $union
            set=$set;$union
        !endif
!!!! end if false isin $row
         :NEXTROW      
     !next r     
!endif
set= !row 2 to -1 of $set
!!! END PROCESS LESCONDS 

!endif

!!! END CNT=0 INITIALISATION (lesconds -> theset)


:SETUNION


!!!! MAKE UNION for SET (interval matrix, disjunctive normal form)
!!!! union of max. disjoint intervals ordered
!!! / no coherence check (done before) 
!!!! FINAL TEST in MODE 0,1 & CREATION THESET when NIV=3

!!!! PROCESS USER SET  (read from var.proc)
!if $mode<=1 and $user=Fin
    set=$theens
    set=!replace \emptyset by in $set
    set=!replace \mathbb{R} by 0,-inf,+inf,0 in $set
!endif


scnt=!rowcnt $set

!!! $mode isin 0,1 and $cnt=0 : process theset also only if several row 
!!! (possible non ordered disjunctions)

!if $mode<=1 and $cnt=0 and $scnt=1
    !goto PRETTYPRINT
!endif

!!! separate intervals having glb=-inf

union=

   !for k = 1 to  $scnt
        int=!row $k of $set
        glb=!item 2 of $int
        !if $glb=-inf
            set1=$set1;$int
        !else
            set2=$set2;$int
        !endif
   !next k
   set1=!row 2 to -1 of $set1
   set2=!row 2 to -1 of $set2

!!! scan set1 (intervals with infinite glb) for greatest lub
!!! make union of them
   !if $set1!=$empty
       theglb=-inf
       thelb=0
       thelub=-inf
       therb=0
       scnt=!rowcnt $set1
       !for k=1 to  $scnt
          int=!row $k of $set1
          lub=!item 3 of $int
          rb = !item 4 of $int
          !if $lub=+inf
!!!! union=R
               union=0,-inf,+inf,0
              !goto ENDUNION
          !else
             !if $thelub=-inf or ($[$lub]=$[$thelub] and $[$rb]=1) or ($[$lub]>$[$thelub]) 
                 thelub=$lub
                 therb=$rb
             !endif
          !endif
       !next k
       first=$thelb,$theglb,$thelub,$therb
   !endif
!!! end set1 non empty 

!!! order set2 (intervals with noninfinite glb) 
!!!! scan intervals in increasing glb order and make union
   !if $set2=$empty
        union=$first
       !goto ENDUNION
   !endif

!!! order set2 and initialize union, if not done previously (by set1)
   !if $set2!=$empty
       col=!column 2 of $set2
       col = !sort numeric item of $col
       order=$wims_sort_order
!!!! first interval in union, if still empty
       !if $first=$empty 
           r=!item 1 of $order
           first = !row $r of $set2
           theglb=!item 2 of $first
           thelub=!item 3 of $first
           thelb=!item 1 of $first
           therb=!item 4 of $first
!!! if first has closed glb and goes to +inf, that's it 
           !if $[$lb]=1 and $thelub=+inf
               union=$first
               !goto ENDUNION
           !endif
       !endif

!!!! make union : maintain first interval (try to extend it) 
!!!! or create second interval, disjoint from first
       last=!item -1 of $order
       !for r in $order
             !if $[$lb]=1 and $thelub=+inf 
                  union=$union;$first
                  !goto ENDUNION
             !endif
             int=!row $r of $set2
             glb=!item 2 of $int
             lub=!item 3 of $int
             lb=!item 1 of $int
             rb =!item 4 of $int
!!! case where intervals overlap
             !if $thelub=+inf
                 !if $[$glb]=$[$theglb] and $thelb<$lb 
                     thelb=$lb
                     first=$thelb,$theglb,$thelub,$therb
                 !endif
             !else
                 !if $[$glb]<$[$thelub] 
                    !if $lub=+inf or $[$thelub]<$[$lub] or ($[$thelub]=$[$lub] and $therb<$rb)
                        thelub=$lub
                        therb=$rb
                        first=$thelb,$theglb,$thelub,$therb
                    !endif
                 !else 
!!! case where interval join
                    !if $[$glb]=$[$thelub] and $[$therb + $lb]>0
                         thelub=$lub
                         therb=$rb
                         first=$thelb,$theglb,$thelub,$therb                    
                    !else
!!! when intervals are disjoints ; create 2nd and put 1st in union
                         union=$union;$first
                         thelub=$lub
                         therb=$rb
                         theglb=$glb
                         thelb=$lb
                         first=$int
                    !endif
                 !endif
             !endif
             !if $r=$last
                 union=$union;$first
             !endif
       !next r
   !endif
 !!!! end set2 non empty
:ENDUNION
set=!nonempty row  $union

!!! end MAKE UNION 


:PRETTYPRINT

!!! PRETTY PRINTING of SET, TEXSOURCE

!if $set=$empty
    ppset=\emptyset
!else
     ppset=
     icnt=!rowcnt $set
     !for i = 1 to $icnt
        int=!row $i of $set
        !if $i!=1
          ou=\cup
        !endif
        lb=!item 1 of $int
        !if $[$lb]=0
           leftbra=]
        !else
           leftbra=[
        !endif
         rb=!item 4 of $int
        !if $[$rb]=0
             rightbra = [
            !else
             rightbra = ]
        !endif  
        borne1=!item 2 of $int
        borne2=!item 3 of $int
       !if $borne1=-inf
            borne1=-\infty
        !else
              borne1=!texmath $borne1
        !endif
        !if $borne2=+inf
            borne2=+\infty
        !else
             borne2=!texmath $borne2
        !endif
        pprint=$leftbra  $borne1 , $borne2 $rightbra 
        ppset = $ppset $ou $pprint
     !next i
!endif
!!! END PRETTY PRINTING

:ENDSET

!if $mode<=1
!if $cnt=0
   theset=$set
   printset=$ppset
!else
   !if   $user=Fin
         !if $set notsametext $theens
             answer=$answer badwrite
         !endif
         theunion=$set
         printunion=$ppset
   !endif
!endif
!endif
