;From  Fanny Pahlplatz - MATH-COPROCESSOR COM

COMMENT ~

> I've found 80xxx.zip and something else that has fp op-codes
> but I haven't found any examples of how to use them. (when and why)

 Here's an example, with some how, when and why chat.

 x = x(t) is a function of time, x' and x" first and second derivatives,

       x" = -x + m(1-xx)x',  m > 0

 Calculate by taking small time steps, h, using
      x(t+h)  = x(t)  + x(t)' * h
      x(t+h)' = x(t)' + x(t)" * h
 or, in short, writing y = x', using the diff.eq. above,
      y = y + (m(1-xx)y - x)h
      x = x + yh

 The differential equation (named a "relaxation oscillation", formulated
 by van der Pol for an electronic circuit) is interesting, because it has
 a periodic "attractor" as a solution: normally you would have to take no
 end of care to preserve precision as you step along the curve, but in this
 case precision takes care of itself.

 If you run it, to see what happens if attractiveness fails, try
 m=0: then x(t) = a * cos t (for any a) would be a solution, but the
 picture becomes a runaway.

 Still, use of floating point is indicated, not for the precision,
 but for the range: x' gets rather large (the curve gets steep)
 while x remains small, about -2.1 < x < 2.1 That would be difficult
 to manage in fixed point.

  > It's that quest for that fast and simple 64 bit signed multiply
  > and divide for those finer fractal images.<g>

 No quest here (though modern math does find much interest in these
 nonlinear diff. eqs.), but it is an attractive family of curves, I
 thought.

COMMENT ENDS ~
              .286
              .model small
              .stack

             .data
 control     dw   0
 oldmode     dw   0
 m           dw   1
 c_100       dw   100
 hinv        dw   20h
 ; Initialize for gridlines at x = 2,1,0,-1,-2 (scale 100).
 ; Proc next_x will write calculated values into ix[].
 ix          LABEL WORD
             REPT  128
             dw   -200,-100,0,100,200
             ENDM

             .code

 ; Comments show the copro stack, top at right. Capitals for results.
 next_x   PROC
 FLD1                  ;  h m x y 1
 FLD    st(2)          ;  h m x y 1 x
 FMUL   st, st(3)      ;  h m x y 1 xx
 FSUB                  ;  h m x y 1-xx
 FLD    st(3)          ;  h m x y 1-xx m
 FMUL                  ;  h m x y M
 FLD    st(1)          ;  h m x y M y
 FMUL                  ;  h m x y My
 FLD    st(2)          ;  h m x y My x
 FSUB                  ;  h m x y My-x
 FLD    st(4)          ;  h m x y My-x h
 FMUL                  ;  h m x y (My-x)h
 FLD    st(1)          ;  h m x y (My-x)h y
 FADD                  ;  h m x y Y
 FXCH                  ;  h m x Y y
 FLD    st(4)          ;  h m x Y y h
 FMUL                  ;  h m x Y yh
 FADDP  st(2), st      ;  h m X Y
 FLD    st(1)          ;  h m X Y X
 FILD   c_100          ;  h m X Y X 100
 FMUL                  ;  h m X Y 100X
 FISTP  ix[si]         ;  h m X Y
 FWAIT
               ret
 next_x        ENDP

 @setport        MACRO   n, value
                 mov     dx,3CEh
                 mov     al,n
                 out     dx,al
                 inc     dx
                 mov     al, value
                 out     dx,al
                 ENDM
 @SR             MACRO   color
                 @setport 0, color
                 ENDM
 @ESR            MACRO   planes
                 @setport 1, planes
                 ENDM
 @BM             MACRO   pixels
                 @setport 8, pixels
                 ENDM

 setpixel    PROC
             mov    cx, si       ; si points to words, so
             shr    cx, 1        ;    count by twos [cfr. below]
             and    cx, 0007     ; pixel position in byte
             mov    ah, 80h
             shr    ah, cl
             @BM    ah           ; Bitmask
             @SR    bl           ; set color
             mov    di, 240      ; address byte =
             sub    di, ix[si]   ;    (240-row)
             shl    di, 4
             mov    ax, di
             shl    ax, 2
             add    di, ax       ;    * 80
             mov    ax, si       ;
             shr    ax, 4        ;    [1 extra, counting by twos]
             add    di, ax       ;    + col >> 3
             mov    ah, es:[di]  ; dummy read/write
             mov    es:[di], ah
             ret
 setpixel    ENDP

 ; gray the old pixel, calculate x(t), color the new pixel, step -- until key
 _display     PROC
 dismore:    mov    bl, 8      ; gray
             call   setpixel
             call   next_x
             mov    bl, 12     ; red
             call   setpixel
             inc    si
             inc    si
             cmp    si, 1280   ; 640 pixels wide; si points to words
             jl     L1
             sub    si, 1280
 L1:         mov    ah, 11h
             int    16h        ; kbhit?
             jz     dismore
             ret
 _display     ENDP

 main:
             mov    ax, @DATA
             mov    ds, ax
             mov    ax, 0A000h
             mov    es, ax

             mov    ah, 0Fh         ; getmode (be kind)
             int    10h
             xor    ah, ah
             mov    [oldmode], ax
             mov    ax, 0012h       ; setmode
             int    10h
             @ESR   0Fh             ; access bitplanes

             ; check for copro; default 03FF -- for mine, anyway.
             FINIT
             FSTCW   control
             FWAIT
             cmp     control, 03FFh
             jnz     g_out

             xor    si, si         ;  timeline

             FLD1                  ;  1
             FILD   hinv           ;  1 20hex
             FDIV                  ;  h=0.08hex
 ; First entry with m=1 (see data seg.)
 ; Initialize x small and level (x'=0), to see it 'find' the curve.
 again:      FILD   m             ; h m
             FLD    st(1)         ; h m x=h
             FLDZ                 ; h m x y=0
             FWAIT
             call   _display
 g_key:      mov    ah, 10h        ; Esc or m = 0 .. 8
             int    16h
             cmp    al, 1Bh
             jz     g_out
             cmp    al, '0'        ; Notice the case m=0 is unstable
             jb     g_key
             cmp    al, '8'
             ja     g_key
             sub    al, '0'
             mov    byte ptr [m], al
             FSTP   st            ; h m x
             FSTP   st            ; h m
             FSTP   st            ; h
             jmp short again
 g_out:      mov    ax, [oldmode]
             int    10h
             mov    ax, 4C00h
             int    21h

 end        main

