;-------------- MAXIMUM OF A FUNCTION --------------
; Find the max value of a function (min with -f(x))
;----------- guillaume.tello@orange.fr--------------

; procedures

#label A set_intervall
#label B set_precision
#label C find_maximum
#label E function

; variables

#reg 1 x
#reg 2 h
#reg 3 quarter                      ; either f(x+h) (1/4) or f(x+2h) (2/4) or f(x+3h) (3/4)
#reg 4 counter
#reg 5 precision
#reg 6 middle                       ; f(x+2h)

;------------------------------------------
; a x%t b A to set the intervall to [a ; b]
;------------------------------------------

LBL set_intervall

    - X/T STO x =                   ; b-a, and a in x
    / 4 = STO h                     ; (b-a)/4 in h
    SUM x                           ; and starts with x+h
    
RTN

;---------------------
; e B to set precision
;---------------------

LBL set_precision

    STO precision

RTN

;---------------------------
; C to calculate the maximum
;---------------------------

LBL find_maximum

    1 X/T                               ; counter lower value
    
    x+{ @h }                            ; x+2h
    / RCL precision =                   
    LNX / 2 LNX + 3 = INT               ; calculates number of loops to reach precision
    IF(x<t)                             ; if lower than 1, then 1!
        1
    ENDIF
    STO counter
    
    middle={ @x SBR f(x) }              ; f(x+2h)
    x-{ @h }                            ; back to x+h
    
    FOR counter
    
        quarter={ @x SBR f(x) }         ; f(x+h)
        x+{ @h }                        ; x+2h
        RCL middle EXC quarter X/T      ; f(x+h) in T    
        RCL quarter                     ; and f(x+2h)
        
        IF(x>=t)                        ; if f(x+2h)>=f(x+h) MAXIMUM not found.....

            x+{ @h }                    ; x+3h
            { @x SBR f(x) }             ; f(x+3h)
                EXC quarter X/T         ; f(x+2h) in T
            RCL quarter                 ; f(x+3h)

            INV x>=t get_back           ; if f(x+3h)<f(x+2h) then MAXIMUM in [x+h;x+3h]

        ELSE                            ; .....ELSE maximum in previous quarter 
            get_back:
                x-{ @h }                ; one step back
                X/T                     ; previous f(.) value
        ENDIF
        
        STO middle                      ; new middle point either f(x+h), f(x+2h), f(x+3h)
        h/{ 2 }                         ; h=h/2 reducing intervall
        x-{ @h }                        ; and adjust x to the first quarter
        
    LOOP                                ; loop until counter=0
    
    RCL x                               ; display MAXIMUM
    
RTN

LBL function

f(x):
    * LNX = +/-
RTN
