         [ d a b c 13 S12 14 ]
         [ c d a b 14 S13 15 ]
         [ b c d a 15 S14 16 ]
-    } [ F ] with-md5-round ;
+    } [ F ] with-md5-round ; inline
 
-: (process-md5-block-G) ( block -- )
+: (process-md5-block-G) ( block v -- )
     {
         [ a b c d 1  S21 17 ]
         [ d a b c 6  S22 18 ]

        [ d a b c 2  S22 30 ]
        [ c d a b 7  S23 31 ]
        [ b c d a 12 S24 32 ]
    } [ G ] with-md5-round ;

: (process-md5-block-H) ( block -- )
    {
        [ a b c d 5  S31 33 ]
        [ d a b c 8  S32 34 ]

checksums.common checksums.stream combinators combinators.smart ;
IN: checksums.md5

TUPLE: md5-state bytes-read state old-state ;

: <md5-state> ( -- md5-state )
    md5-state new
        0 >>bytes-read
        { HEX: 67452301 HEX: efcdab89 HEX: 98badcfe HEX: 10325476 }
        [ clone >>state ] [ clone >>old-state ] bi ;

<PRIVATE

: v-w+ ( v1 v2 -- v3 ) [ w+ ] 2map ;

: update-md5-state ( md5-state -- )
    [ state>> ] [ old-state>> v-w+ dup clone ] [ ] tri
    [ (>>old-state) ] [ (>>state) ] bi ;

: T ( N -- Y )
    sin abs 32 2^ * >integer ; foldable

:: F ( X Y Z -- FXYZ )
    #! F(X,Y,Z) = XY v not(X) Z
    X Y bitand X bitnot Z bitand bitor ; inline

:: G ( X Y Z -- GXYZ )
    #! G(X,Y,Z) = XZ v Y not(Z)
    X Z bitand Y Z bitnot bitand bitor ; inline

: H ( X Y Z -- HXYZ )
    #! H(X,Y,Z) = X xor Y xor Z
    bitxor bitxor ; inline

:: I ( X Y Z -- IXYZ )
    #! I(X,Y,Z) = Y xor (X v not(Z))
    Z bitnot X bitor Y bitxor ; inline

CONSTANT: S11 7
CONSTANT: S12 12
