% MATLAB SCRIPT FILE s322eg1.m  */                                         
%
%    EXAMPLE 2 FOR STATISTICS 322
%    HANDED OUT 8/27/96
%    ILLUSTRATES USE OF if, for AND while "BLOCKS"
%    DOWN LOAD THIS, AND TRY RUNNING IT YOURSELF.
%    PERHAPS CREATE A COPY SO YOU HAVE UNUNHACKED ORIGINAL.

ipar = 1 ;      %  1,...,8
          %    ipar IS SHORT FOR "INTEGER PARAMETER"
          %    PUTTING THIS AT THIS POINT OF THE PROGRAM 
          %    EXPERIMENT WITH CHANIGN THIS TO SEE THE RESULTS


format compact ;
          %    RECALL THIS SAYS "NOT SO MANY BLANK LINES IN SCREEN WRITES"

note = 'Running script s322eg1.m, with: '
ipar
          %    CREATING THE VARIABLE "note" MEANS THAT WHERE WE SAW
          %    "ans" ON THE SCREEN BEFORE, WE NOW SEE "note"
          %    WRITING THE VALUE OF ipar TO THE SCREEN CAN AVOID
          %    CONFUSION ABOUT WHICH PART OF THE PROGRAM IS RUNNING



if ipar == 1 ;        %  THEN RUN THE NEXT "BLOCK" (I.E. SET OF LINES
                      %  OF CODE), WHICH IS PART 1 OF "if STATEMENTS"

  %    "IF BLOCKS", START WITH AN "if" LINE, AND END WITH A LINE WITH
  %    ONLY "end".  AFTER THE IF IN THE FIRST LINE, IS AN EXPRESSION
  %    TAKING ON ONLY THE VALUES  1  FOR "TRUE", OR  0  FOR "FALSE"
  %    WHEN THE VALUE IS  1,  THE CODE IN THE BLOCK IS EXECUTED
  %    WHEN THE VALUE IS  0,  THE CODE IN THE BLOCK IS SKIPPED OVER

  if 1 ;
    note = ['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10] ;
          %    RECALL STRINGS, AND 10 IS "LINE FEED"           
    note = [note,'!!!  Did the stuff in if block number 1  !!!',10] ;
    note = [note,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10,10]
          %    RECALL NO SEMICOLON AT END DOES SCREEN WRITE
  end ;

  if 0 ;
    note = ['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10] ;
    note = [note,'!!!  Did the stuff in if block number 2  !!!',10] ;
    note = [note,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10,10]
  end ;
  note = 'After if block number 2 now'

  %    IF BLOCKS BECOME VERY USEFUL WHEN A VARIABLE IS USED TO 
  %    DECIDE WHEN THEY ARE EXECUTED
  a = 0 ;
  if a ;
    note = ['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10] ;
    note = [note,'!!!  Did the stuff in if block number 3  !!!',10] ;
    note = [note,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10,10]
  end ;
  note = 'After if block number 3 now'

  a = 1 ;
  if a ;
    note = ['!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10] ;
    note = [note,'!!!  Did the stuff in if block number 4  !!!',10] ;
    note = [note,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',10,10]
  end ;
  note = 'After if block number 4 now'

  %    READABILITY (VERY IMPORTANT IF YOU NEED TO LOOK A PROGRAM
  %    MONTHS LATER, BUT USEFUL IN ANY SERIOUS WORK) IS ENHANCED 
  %    BY INDENTING CODE INSIDE if BLOCKS


elseif ipar == 2 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 2 OF "if" STATEMENTS

  %    USING 0'S AND 1'S TO CONTROL if STATEMENT IS NOT VERY CONVENIENT.
  %    MORE IMPLEMENTATION IS DONE THROUGH "RELATIONAL OPERATORS" (SEE
  %    PAGE 33 OF THE USER'S GUIDE FOR A FULL LIST OF THESE), WHICH 
  %    RETURN  0  OR  1,  DEPENDING ON WHETHER THE INDICATED
  %    RELATIONSHIP IS "TRUE" OR "FALSE"

  a = 27
  note = 'The relation "a = 27" returns '
  (a == 27)
          %    "==" DISTINGUISHES FROM THE ASSIGNMENT OPERATOR "="
  note = 'The relation "a = 3" returns '
  (a == 3)
  note = 'The relation "a > 12" returns '
  (a > 12)
  note = 'The relation "a < 27" returns '
  (a < 27)
  note = 'The relation "a <= 27" returns '
  (a <= 27)

elseif ipar == 3 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 3 OF "if" STATEMENTS

  %    USING THE ABOVE TWO IDEAS TOGETHER MAKES IF STATEMENTS
  %    VERY SIMPLE AND NATURAL TO USE.  IN FACT YOU CAN IGNORE 
  %    THE 0, 1 CONTROL ASPECT OF if STATEMENTS

  a = 5 
  b = 8  
  if a < b ;
    note = 'Write this if a < b'
  end ;

  if a ~= b ;
    note = 'Write this if a /= b'
  end ;

  if a >= b ;
    note = 'Write this if a >= b'
  end ;

  if 3 * a >= 2 * b - 1 ;
          %    ARITHMETIC OPERATIONS ARE DONE BEFORE RELATIONAL OPERATIONS
    note = 'Write this if 3a >= 2b-1'
  end ;


elseif ipar == 4 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 4 OF "if" STATEMENTS

  %    CONTROL STATEMENTS CAN BE COMBINED IN USEFUL WAYS USING "LOGICAL
  %    OPERATORS:
  %        &   "AND"
  %        |   "OR"
  %        ~   "NOT"
  %    THESE ARE ALL JUST "BOOLEAN OPERATORS" ON THE 0'S AND 1'S
  %    (SEE THE "SEE ALSO" PART OF PAGE 34 OF THE REFERENCE GUIDE 
  %    FOR A LIST OF OTHER RELATED OPERATIONS)

  a = 4
  b = 2 
  if a == 4 & b == 2 ;
    note = 'Write this if a=4 and b=2'
  end ;

  if a == 4 & b == 7 ;
    note = 'Write this if a=4 and b=7'
  end ;

  if ~(a == 4) ;
    note = 'Write this if not a=4'
  end ;

  if ~(a == 73) ;
    note = 'Write this if not a=73'
  end ;

elseif ipar == 5 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 5 OF "if" STATEMENTS

  %    A BLOCK OF CODE TO BE EXECUTED WHEN THE if CONTROL IS 0,
  %    CAN BE ADDED, JUST AFTER A LINE CONTAINING "else"
  %    THIS CAN EXPANDED TO SEVERAL CONDITIONS, USING "elseif"

  a = 3 

  if a ~= 4 ;
    note = 'Write this if a/=4'
  else ;
    note = 'Write this if a=4'
  end ;

  if a == 4 ;
    note = 'Write this if a=4'
  else ;
    note = 'Write this if a/=4'
  end ;

  if a < 3 ;
    note = 'Write this if a<3'
  elseif a == 3 ;
    note = 'Write this if a=3'
  elseif a > 3 ;
    note = 'Write this if a>3'
          %    COULD HAVE USED JUST "else" AS WELL
  end ;


elseif ipar == 6 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 1 OF "for" LOOPS

  %    for LOOPS ARE BLOCKS OF CODE WHOSE EXECUTION IS REPEATED A
  %    NUMBER OF TIMES (MUCH MORE CONVENIENT THAN COPYING THE BLOCK
  %    MANY TIMES IN THE PROGRAM!).  THE BLOCK IS STARTED WITH A
  %    "for" STATEMENT, THAT CONTROLS HOW MANY THE BLOCK IS EXECUTED,
  %    AND DEFINES AN INDEX THAT CAN BE USED IN THE BLOCK.  THE BLOCK 
  %    ENDS WITH AN END STATEMENT.

  fact = 1 ;
  for i = 1:1:4 ;
          %    THIS SAYS RUN THROUGH THE VECTOR i = 1,2,3,4
    note = 'Working on "i = 1:1:4 loop", with '
    i
          %    STATEMENTS LIKE THIS CAN BE USEFUL TO PUT INTO
          %    PROGRAMS TO SEE HOW FAR YOU HAVE GONE (ESPECIALLY
          %    USEFUL IN LONG PROGRAMS, WHICH CAN DRIVE YOU CRAZY
          %    IF YOU STARE TOO LONG AT A BLANK SCREEN).  BUT AVOID
          %    TOO MANY SUCH STATEMENTS, AS MANY SCREEN WRITES CAN 
          %    SIGNIFICANTLY SLOW DOWN THE EXECUTION
    fact = fact * i ;
  end ;

  %    THE ABOVE LOOP CALCULATED 4 FACTORIAL:
  note = 'By a loop calculation, 4! is:'
  fact

  %    HERE IS ANOTHER WAY TO CALCULATE 4 FACTORIAL:
  note = 'By a matrix product calculation, 4! is:'
  fact = prod((1:1:4)')
           %    IF YOU DON'T UNDERSTAND ANY PART OF THIS, TRY IT
           %    BY ITSELF TO SEE WHAT IT DOES.  ALSO YOU MIGHT 
           %    TRY THIS WITHOUT THE TRANSPOSE TO SEE WHAT HAPPENS
 
  %    HERE IS AN EVEN "HIGHER TECH" WAY TO CALCULATE 4 FACTORIAL:
  note = 'By the Gamma Function, 4! is:'
  fact = gamma(5)
  

elseif ipar == 7 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 1 OF "while" LOOPS

  %    "while" LOOPS DO NOT HAVE THE EXPLICIT INDEX OF "for" LOOPS,
  %    BUT INSTEAD CONTINUE TO EXECUTE AS LONG AS THE CONDITION
  %    ON THE "while" LINE IS TRUE.

  %    START WITH THE MATRIX:
  x = [0:10:30 ; 0:20:60] 

  %    IT IS OFTEN USEFUL TO KNOW HOW MANY ROWS AND COLUMNS IN A MATRIX:
  [rowsx,colsx] = size(x)
          %    HERE IS A DIFFERENT TYPE OF ASSIGNMENT STATEMENT
          %    THIS CREATES THE VARIABLES rowsx AND colsx

  %    HERE IS A BAD WAY TO CHANGE THE ORDER OF THE COLUMNS 
  y = x(:,colsx) ;
          %    PICKS OFF JUST THE LAST COLUMN
  while size(y,2) < colsx ;
          %    size( ,2) GIVES THE NUMBER OF COLUMNS
     y = [y,x(:,colsx-size(y,2))] ;
%     y
          %    THIS LINE WAS USEFUL AT THE DEVELOPMENTAL STAGE,
          %    TO SEE THAT THE WRITE THING WAS HAPPENING WITH
          %    THIS COMPLICATED CONSTRUCTION
  end ;        

  note = 'x, with columns reversed is:'   
  y


  %    A MUCH BETTER WAY TO REVERSE COLUMNS IS:
  y = fliplr(x) ;
          %  SHORT FOR "FLIP LEFT TO RIGHT"
          %  SIMILARLY USEFUL ARE:
          %      flipud     "FLIP UP TO DOWN"
          %      rot90      "ROTATE 90 DEGREES"
  note = 'x, with columns directly reversed is:'   
  y

  %    YOU MIGHT THING ABOUT, THEN TRY:
  %flipud(x')'
  %rot90(flipud(rot90(x)),3)  


elseif ipar == 8 ;      %    THEN RUN THE NEXT LINES OF CODE,
                        %    WHICH IS PART 2 OF "for" LOOPS

  %    LOOPS ARE EASY TO WORK WITH, AND ARE EVEN "NATURAL" IF YOU ARE
  %    ACCUSTOMED TO LOW LEVEL LANGUAGES LIKE FORTRAN OR C, BUT IT IS
  %    VERY IMPORTANT TO REALIZE THAT THEY CAN BE MUCH SLOWER THAN 
  %    CORRESPONDING DIRECT MATRIX OPERATIONS IN MATLAB


  n = 10000 ;
  x = rand(n,1) ;
          %    AN nx1 MATRIX OF PSEUDO RANDOM REALIZATIONS FROM
          %    THE UNIF(0,1) DISTRIBUTION.  THE "SEED" COMES FROM
          %    THE COMPUTER CLOCK

  %    NOW TRY EXPONENTIATING THE SQUARE ROOT OF THE ENTRIES OF 
  %    x IN VARIOUS WAYS:

  %    HERE IS A DELIBERATLY DUMB WAY:
  note = 'Start very slow loop version' ;
  tic ;   %    THIS STARTS A "TIMER"
  for i = 1:1:length(x) ;
          %    COMMAND length GIVES THE NUMBER OF ENTRIES IN A VECTOR
    if rem(i,50) == 0 
          %    REMAINDER AFTER DIVISION OF i BY 50
          %    EXECUTE THESE STATEMENTS EVERY 50TH STEP
      note = 'Working on exponentiation number: ' ;
      i
    end ;    
    z = sqrt(x) ;
          %   THIS IS DELIBERATELY SLOW, TO ILLUSTRTE WHAT NOT TO DO
          %   LOOPS.  THIS COULD BE SPEEDED UP BY ANY OF:
          %       1.  DO JUST A SCALAR SQUARE ROOT:  z = sqrt(x(i,1))
          %       2.  DO THE MATRIX sqrt OUTSIDE OF THE LOOP
    if i == 1 ;       
      y = exp(z(i,1)) ;
    elseif i > 1 ;
      y = [y; exp(z(i,1))] ;
    end ;
          %   THIS BLOCK CREATES THE Y VECTOR FIRST TIME THROUGH
          %   THEN APPENDS TO IT LATER
  end ;
  note = 'The very slow loop version ran in:' ;
  toc ;   %    THIS STOPS THE TIMER, AND DISPLAYS THE TIME TAKEN
  note = 'Hit any key to continue' ;
  pause ;
          %    THIS TELLS MATLAB TO WAIT UNTIL THE USER HITS A KEY
          %    THE PREVIOUS MESSAGE IS A REMINDER THAT MATLAB IS WAITING


  %    NOW IMPROVE THE LOOP BY A MORE INTELLIGENT CALCULATION OF
  %    THE SQUARE ROOT
  note = 'Start slow loop version' ;
  tic ;  
  z = sqrt(x) ;
          %    NOW THIS IS DONE OUTSIDE THE LOOP, TO AVOID 
          %    UNNECESSARILY REPEATING IT
  for i = 1:1:length(x) ;
    if rem(i,50) == 0 
      note = 'Working on exponentiation number: ' ;
      i
    end ;    
    if i == 1 ;       
      y = exp(z(i,1)) ;
    elseif i > 1 ;
      y = [y; exp(z(i,1))] ;
    end ;
  end ;
  note = 'The slow loop version ran in:' ;
  toc ;
  note = 'Hit any key to continue' ;
  pause ;


  %    NOW IMPROVE THE LOOP BY GETTING RID OF THE SCREEN WRITE
  %    AND THE CONDITIONAL PART
  %    YOU MIGHT WANT TO SEE WHAT MAKES THE BIGGER DIFFERENCE BY
  %    TRYING EACH OF THESE THINGS INDIVIDUALLY
  note = 'Start fast loop version' ;
  tic ;  
  z = sqrt(x) ;
  y = 0 ;
  for i = 1:1:length(x) ;
      y(i) = exp(z(i,1)) ;
          %    MATLAB WILL AUTOMATICALLY ADJUST THE SIZE OF VECTORS
  end ;
  note = 'The fast loop version ran in:' ;
  toc ;
  note = 'Hit any key to continue' ;
  pause ;


  %    BUT SERIOUS SPEED COMES FROM AVOIDING LOOPS ALTOGETHER, 
  %    AND DOING MATRIX CALCULATIONS
  note = 'Start matrix version' ;
  tic ;  
  z = sqrt(x) ;
  y = exp(z) ;
  note = 'The matrix version ran in:' ;
  toc ;
  note = 'Hit any key to continue' ;
  pause ;

  %    I TRIED THIS PROGRAM ON A 66MhZ 486 PC, USING n = 2000,
  %    AND ELAPSED TIMES WERE:
  %        VERY SLOW LOOP:  27.57 SECS
  %             SLOW LOOP:  11.43 SECS
  %             FAST LOOP:   1.59 SECS
  %         DIRECT MATRIX:    .06 SECS

  %    IN ANTICIPATION OF THIS EXECUTING MUCH FASTER ON A SUN,
  %    I HAVE SET n = 10000 ABOVE.  IF YOU DO THIS ON A PC, 
  %    SET n BACK TO 2000.

  %    NOTE THAT THE SPEED SAVINGS ABOVE ARE ON THE
  %    ORDER OF A FACTOR OF 1000.  IN MORE COMPLICATED SETTINGS  
  %    (E.G. THINGS LIKE NESTED LOOPS), EVEN GREATER FACTORS CAN BE HAD.  
  %    FOR SERIOUS NUMBER CRUNCHING, THIS CAN BE THE DIFFERENCE BETWEEN:  
  %            A FEW SECONDS     &     AN HOUR  
  %            OVER NIGHT        &     A YEAR   
  %            ONE MONTH         &     YOUR LIFE (WELL YOUR COMPUTER'S LIFE!)
  %
  %    MORAL: IN MATLAB DO THINGS IN MATRIX TERMS WHEREVER POSSIBLE!!!  
  %
  %    IF YOU ARE ACCUSTOMED TO THINKING IN TERMS OF LOOPS, IT WILL TAKE
  %    SOME EFFORT, BUT IT IS WORTHWHILE.

end ;



