]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://github.com/Blei/factor
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 10 Aug 2009 21:18:19 +0000 (16:18 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 10 Aug 2009 21:18:19 +0000 (16:18 -0500)
15 files changed:
basis/alien/arrays/arrays.factor
basis/alien/c-types/c-types.factor
basis/alien/complex/complex-tests.factor
basis/alien/complex/functor/functor.factor
basis/alien/structs/structs.factor
basis/compiler/tree/debugger/debugger.factor
basis/compiler/tree/modular-arithmetic/modular-arithmetic-tests.factor
basis/compiler/tree/propagation/info/info.factor
basis/compiler/tree/propagation/known-words/known-words.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/compiler/tree/propagation/recursive/recursive-tests.factor
basis/compiler/tree/propagation/recursive/recursive.factor
basis/math/intervals/intervals.factor
basis/specialized-arrays/functor/functor.factor
extra/benchmark/yuv-to-rgb/yuv-to-rgb.factor [new file with mode: 0644]

index 4786c85bd469068b49d0b68be6e68b91d8987919..d793814c28925225b1ae9ff13ff5df2b5790c4c4 100755 (executable)
@@ -11,6 +11,8 @@ M: array c-type ;
 
 M: array c-type-class drop object ;
 
+M: array c-type-boxed-class drop object ;
+
 M: array heap-size unclip [ product ] [ heap-size ] bi* * ;
 
 M: array c-type-align first c-type-align ;
@@ -45,8 +47,9 @@ PREDICATE: string-type < pair
 
 M: string-type c-type ;
 
-M: string-type c-type-class
-    drop object ;
+M: string-type c-type-class drop object ;
+
+M: string-type c-type-boxed-class drop object ;
 
 M: string-type heap-size
     drop "void*" heap-size ;
index 7807113999a4f27de2f733d1d4a027921b91f74d..2eba6a2b9e76cd9cb47434716a7df391c82248ec 100755 (executable)
@@ -15,6 +15,7 @@ DEFER: *char
 
 TUPLE: abstract-c-type
 { class class initial: object }
+{ boxed-class class initial: object }
 { boxer-quot callable }
 { unboxer-quot callable }
 { getter callable }
@@ -76,6 +77,12 @@ M: abstract-c-type c-type-class class>> ;
 
 M: string c-type-class c-type c-type-class ;
 
+GENERIC: c-type-boxed-class ( name -- class )
+
+M: abstract-c-type c-type-boxed-class boxed-class>> ;
+
+M: string c-type-boxed-class c-type c-type-boxed-class ;
+
 GENERIC: c-type-boxer ( name -- boxer )
 
 M: c-type c-type-boxer boxer>> ;
@@ -300,6 +307,7 @@ CONSTANT: primitive-types
 [
     <c-type>
         c-ptr >>class
+        c-ptr >>boxed-class
         [ alien-cell ] >>getter
         [ [ >c-ptr ] 2dip set-alien-cell ] >>setter
         bootstrap-cell >>size
@@ -311,6 +319,7 @@ CONSTANT: primitive-types
 
     <long-long-type>
         integer >>class
+        integer >>boxed-class
         [ alien-signed-8 ] >>getter
         [ set-alien-signed-8 ] >>setter
         8 >>size
@@ -321,6 +330,7 @@ CONSTANT: primitive-types
 
     <long-long-type>
         integer >>class
+        integer >>boxed-class
         [ alien-unsigned-8 ] >>getter
         [ set-alien-unsigned-8 ] >>setter
         8 >>size
@@ -331,6 +341,7 @@ CONSTANT: primitive-types
 
     <c-type>
         integer >>class
+        integer >>boxed-class
         [ alien-signed-cell ] >>getter
         [ set-alien-signed-cell ] >>setter
         bootstrap-cell >>size
@@ -341,6 +352,7 @@ CONSTANT: primitive-types
 
     <c-type>
         integer >>class
+        integer >>boxed-class
         [ alien-unsigned-cell ] >>getter
         [ set-alien-unsigned-cell ] >>setter
         bootstrap-cell >>size
@@ -351,6 +363,7 @@ CONSTANT: primitive-types
 
     <c-type>
         integer >>class
+        integer >>boxed-class
         [ alien-signed-4 ] >>getter
         [ set-alien-signed-4 ] >>setter
         4 >>size
@@ -361,6 +374,7 @@ CONSTANT: primitive-types
 
     <c-type>
         integer >>class
+        integer >>boxed-class
         [ alien-unsigned-4 ] >>getter
         [ set-alien-unsigned-4 ] >>setter
         4 >>size
@@ -371,6 +385,7 @@ CONSTANT: primitive-types
 
     <c-type>
         fixnum >>class
+        fixnum >>boxed-class
         [ alien-signed-2 ] >>getter
         [ set-alien-signed-2 ] >>setter
         2 >>size
@@ -381,6 +396,7 @@ CONSTANT: primitive-types
 
     <c-type>
         fixnum >>class
+        fixnum >>boxed-class
         [ alien-unsigned-2 ] >>getter
         [ set-alien-unsigned-2 ] >>setter
         2 >>size
@@ -391,6 +407,7 @@ CONSTANT: primitive-types
 
     <c-type>
         fixnum >>class
+        fixnum >>boxed-class
         [ alien-signed-1 ] >>getter
         [ set-alien-signed-1 ] >>setter
         1 >>size
@@ -401,6 +418,7 @@ CONSTANT: primitive-types
 
     <c-type>
         fixnum >>class
+        fixnum >>boxed-class
         [ alien-unsigned-1 ] >>getter
         [ set-alien-unsigned-1 ] >>setter
         1 >>size
@@ -420,6 +438,7 @@ CONSTANT: primitive-types
 
     <c-type>
         float >>class
+        float >>boxed-class
         [ alien-float ] >>getter
         [ [ >float ] 2dip set-alien-float ] >>setter
         4 >>size
@@ -432,6 +451,7 @@ CONSTANT: primitive-types
 
     <c-type>
         float >>class
+        float >>boxed-class
         [ alien-double ] >>getter
         [ [ >float ] 2dip set-alien-double ] >>setter
         8 >>size
index 0bff73b898dae2ddc88e873c4c0d3d722461275c..e84bb322e29020a99742ca13539aa20f66878a9f 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: tools.test alien.complex kernel alien.c-types alien.syntax
-namespaces ;
+namespaces math ;
 IN: alien.complex.tests
 
 C-STRUCT: complex-holder
@@ -16,3 +16,7 @@ C-STRUCT: complex-holder
 ] unit-test
 
 [ C{ 1.0 2.0 } ] [ "h" get complex-holder-z ] unit-test
+
+[ complex ] [ "complex-float" c-type-boxed-class ] unit-test
+
+[ complex ] [ "complex-double" c-type-boxed-class ] unit-test
\ No newline at end of file
index 59bf3451b87cd70b23a6a06318114780ba763f21..98d412639f8c239a0b50e76848b1a559fad8a5f6 100644 (file)
@@ -30,7 +30,7 @@ define-struct
 T c-type
 <T> 1quotation >>unboxer-quot
 *T 1quotation >>boxer-quot
-number >>class
+number >>boxed-class
 drop
 
 ;FUNCTOR
index 4154ad1dd8f3aef9e1f3d1f7b967d2d1499b6f9e..5c1fb4063b90f78dff63428173bc87be66eb558c 100755 (executable)
@@ -39,6 +39,7 @@ M: struct-type stack-size
     [ [ align ] keep ] dip
     struct-type new
         byte-array >>class
+        byte-array >>boxed-class
         swap >>fields
         swap >>align
         swap >>size
index d6906d63482d5fa650b6ca0aacc6ca6499c346b2..6f313320d036fe7e97b440a9e198d17c57cd9985 100644 (file)
@@ -16,6 +16,7 @@ compiler.tree.builder
 compiler.tree.optimizer
 compiler.tree.combinators
 compiler.tree.checker
+compiler.tree.identities
 compiler.tree.dead-code
 compiler.tree.modular-arithmetic ;
 FROM: fry => _ ;
@@ -208,6 +209,7 @@ SYMBOL: node-count
         normalize
         propagate
         cleanup
+        apply-identities
         compute-def-use
         remove-dead-code
         compute-def-use
index 13555d45f7b7d663d7a0440720602fc66f46c106..a9415adbd706db161bbf87d092dcce989762a1d3 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 IN: compiler.tree.modular-arithmetic.tests
 USING: kernel kernel.private tools.test math math.partial-dispatch
-math.private accessors slots.private sequences strings sbufs
+math.private accessors slots.private sequences sequences.private strings sbufs
 compiler.tree.builder
 compiler.tree.normalization
 compiler.tree.debugger
@@ -171,3 +171,8 @@ cell {
 [ [ [ { fixnum fixnum } declare + ] 2dip set-alien-signed-8 ] test-modular-arithmetic ] unit-test
 
 [ t ] [ [ { fixnum byte-array } declare [ + ] with map ] { + fixnum+ >fixnum } inlined? ] unit-test
+
+[ t ] [
+    [ 0 10 <byte-array> 10 [ 1 pick 0 + >fixnum pick set-nth-unsafe [ 1 + >fixnum ] dip ] times ]
+    { >fixnum } inlined?
+] unit-test
\ No newline at end of file
index 98baba3e973431b20434b3910507c6837b4c7da0..cae8d6cde684571091108db0aa00983e275554fc 100644 (file)
@@ -2,9 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs classes classes.algebra classes.tuple
 classes.tuple.private kernel accessors math math.intervals namespaces
-sequences words combinators combinators.short-circuit byte-arrays
-strings arrays layouts cpu.architecture compiler.tree.propagation.copy
- ;
+sequences sequences.private words combinators
+combinators.short-circuit byte-arrays strings arrays layouts
+cpu.architecture compiler.tree.propagation.copy ;
 IN: compiler.tree.propagation.info
 
 : false-class? ( class -- ? ) \ f class<= ;
@@ -37,10 +37,6 @@ CONSTANT: null-info T{ value-info f null empty-interval }
 
 CONSTANT: object-info T{ value-info f object full-interval }
 
-: class-interval ( class -- interval )
-    dup real class<=
-    [ "interval" word-prop [-inf,inf] or ] [ drop f ] if ;
-
 : interval>literal ( class interval -- literal literal? )
     #! If interval has zero length and the class is sufficiently
     #! precise, we can turn it into a literal
@@ -85,6 +81,23 @@ UNION: fixed-length array byte-array string ;
         [ [ class>> real class<= ] [ interval>> empty-interval eq? ] bi and ]
     } 1|| ;
 
+: min-value ( class -- n ) fixnum eq? [ most-negative-fixnum ] [ -1/0. ] if ;
+
+: max-value ( class -- n ) fixnum eq? [ most-positive-fixnum ] [ 1/0. ] if ;
+
+: class-interval ( class -- i ) fixnum eq? [ fixnum-interval ] [ full-interval ] if ;
+
+: wrap-interval ( interval class -- interval' )
+    {
+        { fixnum [ interval->fixnum ] }
+        { array-capacity [ max-array-capacity [a,a] interval-rem ] }
+        [ drop ]
+    } case ;
+
+: init-interval ( info -- info )
+    dup [ interval>> full-interval or ] [ class>> ] bi wrap-interval >>interval
+    dup class>> integer class<= [ [ integral-closure ] change-interval ] when ; inline
+
 : init-value-info ( info -- info )
     dup literal?>> [
         init-literal-info
@@ -93,8 +106,7 @@ UNION: fixed-length array byte-array string ;
             null >>class
             empty-interval >>interval
         ] [
-            [ [-inf,inf] or ] change-interval
-            dup class>> integer class<= [ [ integral-closure ] change-interval ] when
+            init-interval
             dup [ class>> ] [ interval>> ] bi interval>literal
             [ >>literal ] [ >>literal? ] bi*
         ] if
@@ -107,8 +119,7 @@ UNION: fixed-length array byte-array string ;
     init-value-info ; foldable
 
 : <class-info> ( class -- info )
-    dup word? [ dup "interval" word-prop ] [ f ] if [-inf,inf] or
-    <class/interval-info> ; foldable
+    f <class/interval-info> ; foldable
 
 : <interval-info> ( interval -- info )
     <value-info>
index a2955ca699a9a136f9ac1d9450b146edc6ca3881..8c4e81f41d8007398bf15eda9d73073b620b4364 100644 (file)
@@ -18,14 +18,6 @@ compiler.tree.propagation.call-effect
 compiler.tree.propagation.transforms ;
 IN: compiler.tree.propagation.known-words
 
-\ fixnum
-most-negative-fixnum most-positive-fixnum [a,b]
-"interval" set-word-prop
-
-\ array-capacity
-0 max-array-capacity [a,b]
-"interval" set-word-prop
-
 { + - * / }
 [ { number number } "input-classes" set-word-prop ] each
 
@@ -53,8 +45,8 @@ most-negative-fixnum most-positive-fixnum [a,b]
     { fixnum bignum integer rational float real number object }
     [ class<= ] with find nip ;
 
-: fits? ( interval class -- ? )
-    "interval" word-prop interval-subset? ;
+: fits-in-fixnum? ( interval -- ? )
+    fixnum-interval interval-subset? ;
 
 : binary-op-class ( info1 info2 -- newclass )
     [ class>> ] bi@
@@ -66,7 +58,7 @@ most-negative-fixnum most-positive-fixnum [a,b]
     [ [ interval>> ] bi@ ] dip call ; inline
 
 : won't-overflow? ( class interval -- ? )
-    [ fixnum class<= ] [ fixnum fits? ] bi* and ;
+    [ fixnum class<= ] [ fits-in-fixnum? ] bi* and ;
 
 : may-overflow ( class interval -- class' interval' )
     over null-class? [
@@ -219,14 +211,7 @@ generic-comparison-ops [
 
     { >integer integer }
 } [
-    '[
-        _
-        [ nip ] [
-            [ interval>> ] [ class-interval ] bi*
-            interval-intersect
-        ] 2bi
-        <class/interval-info>
-    ] "outputs" set-word-prop
+    '[ _ swap interval>> <class/interval-info> ] "outputs" set-word-prop
 ] assoc-each
 
 { numerator denominator }
@@ -262,7 +247,7 @@ generic-comparison-ops [
             [ string>number 8 * 2^ 1- 0 swap [a,b] ]
         }
     } cond
-    [ fixnum fits? fixnum integer ? ] keep <class/interval-info>
+    [ fits-in-fixnum? fixnum integer ? ] keep <class/interval-info>
     '[ 2drop _ ] "outputs" set-word-prop
 ] each
 
index 46d98c28b6c60673c3fa8c60676be447bdf74e5a..59631d04c67c6b20b19673c741263fee9af69b33 100644 (file)
@@ -713,6 +713,20 @@ TUPLE: littledan-2 { from read-only } { to read-only } ;
 
 [ V{ 1 } ] [ [ { } length 1+ f <array> length ] final-literals ] unit-test
 
+! generalize-counter is not tight enough
+[ V{ fixnum } ] [ [ 0 10 [ 1 + >fixnum ] times ] final-classes ] unit-test
+
+[ V{ fixnum } ] [ [ 0 10 [ 1 + >fixnum ] times 0 + ] final-classes ] unit-test
+
+! Coercions need to update intervals
+[ V{ f } ] [ [ 1 2 ? 100 shift >fixnum 1 = ] final-literals ] unit-test
+
+[ V{ t } ] [ [ >fixnum 1 + >fixnum most-positive-fixnum <= ] final-literals ] unit-test
+
+[ V{ t } ] [ [ >fixnum 1 + >fixnum most-negative-fixnum >= ] final-literals ] unit-test
+
+[ V{ f } ] [ [ >fixnum 1 + >fixnum most-negative-fixnum > ] final-literals ] unit-test
+
 ! Mutable tuples with circularity should not cause problems
 TUPLE: circle me ;
 
index cf72a2a135e809f34ecb2c9a1952d1cbffe9f478..db427d34af51e6aced5b03e345e49d250d46a019 100644 (file)
@@ -1,19 +1,51 @@
 IN: compiler.tree.propagation.recursive.tests
 USING: tools.test compiler.tree.propagation.recursive
-math.intervals kernel ;
+math.intervals kernel math literals layouts ;
 
 [ T{ interval f { 0 t } { 1/0. t } } ] [
     T{ interval f { 1 t } { 1 t } }
-    T{ interval f { 0 t } { 0 t } } generalize-counter-interval
+    T{ interval f { 0 t } { 0 t } }
+    integer generalize-counter-interval
+] unit-test
+
+[ T{ interval f { 0 t } { $[ most-positive-fixnum ] t } } ] [
+    T{ interval f { 1 t } { 1 t } }
+    T{ interval f { 0 t } { 0 t } }
+    fixnum generalize-counter-interval
 ] unit-test
 
 [ T{ interval f { -1/0. t } { 10 t } } ] [
     T{ interval f { -1 t } { -1 t } }
-    T{ interval f { 10 t } { 10 t } } generalize-counter-interval
+    T{ interval f { 10 t } { 10 t } }
+    integer generalize-counter-interval
+] unit-test
+
+[ T{ interval f { $[ most-negative-fixnum ] t } { 10 t } } ] [
+    T{ interval f { -1 t } { -1 t } }
+    T{ interval f { 10 t } { 10 t } }
+    fixnum generalize-counter-interval
 ] unit-test
 
 [ t ] [
     T{ interval f { 1 t } { 268435455 t } }
     T{ interval f { -268435456 t } { 268435455 t } } tuck
-    generalize-counter-interval =
+    integer generalize-counter-interval =
+] unit-test
+
+[ t ] [
+    T{ interval f { 1 t } { 268435455 t } }
+    T{ interval f { -268435456 t } { 268435455 t } } tuck
+    fixnum generalize-counter-interval =
+] unit-test
+
+[ full-interval ] [
+    T{ interval f { -5 t } { 3 t } }
+    T{ interval f { 2 t } { 11 t } }
+    integer generalize-counter-interval
+] unit-test
+
+[ $[ fixnum-interval ] ] [
+    T{ interval f { -5 t } { 3 t } }
+    T{ interval f { 2 t } { 11 t } }
+    fixnum generalize-counter-interval
 ] unit-test
index 64b7ba4609309a58537296a4d7da7c7f78b82f0d..eb4158e7563ec7487460a3aff2958a8afd8dff2c 100644 (file)
@@ -1,7 +1,7 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences accessors arrays fry math.intervals
-combinators namespaces
+USING: kernel sequences accessors arrays fry math math.intervals
+layouts combinators namespaces locals
 stack-checker.inlining
 compiler.tree
 compiler.tree.combinators
@@ -24,20 +24,26 @@ IN: compiler.tree.propagation.recursive
     [ label>> calls>> [ node>> node-input-infos ] map flip ]
     [ latest-input-infos ] bi ;
 
-: generalize-counter-interval ( interval initial-interval -- interval' )
+:: generalize-counter-interval ( interval initial-interval class -- interval' )
     {
-        { [ 2dup interval-subset? ] [ empty-interval ] }
-        { [ over empty-interval eq? ] [ empty-interval ] }
-        { [ 2dup interval>= t eq? ] [ 1/0. [a,a] ] }
-        { [ 2dup interval<= t eq? ] [ -1/0. [a,a] ] }
-        [ [-inf,inf] ]
-    } cond interval-union nip ;
+        { [ interval initial-interval interval-subset? ] [ initial-interval ] }
+        { [ interval empty-interval eq? ] [ initial-interval ] }
+        {
+            [ interval initial-interval interval>= t eq? ]
+            [ class max-value [a,a] initial-interval interval-union ]
+        }
+        {
+            [ interval initial-interval interval<= t eq? ]
+            [ class min-value [a,a] initial-interval interval-union ]
+        }
+        [ class class-interval ]
+    } cond ;
 
 : generalize-counter ( info' initial -- info )
     2dup [ not ] either? [ drop ] [
         2dup [ class>> null-class? ] either? [ drop ] [
             [ clone ] dip
-            [ [ drop ] [ [ interval>> ] bi@ generalize-counter-interval ] 2bi >>interval ]
+            [ [ drop ] [ [ [ interval>> ] bi@ ] [ drop class>> ] 2bi generalize-counter-interval ] 2bi >>interval ]
             [ [ drop ] [ [ slots>> ] bi@ [ generalize-counter ] 2map ] 2bi >>slots ]
             [ [ drop ] [ [ length>> ] bi@ generalize-counter ] 2bi >>length ]
             tri
index 39582eafa43e84bbe27bc232e01a428827c33e73..8b07394596700ea30b3b35c10f0a3a12668edfd2 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 ! Based on Slate's src/unfinished/interval.slate by Brian Rice.
 USING: accessors kernel sequences arrays math math.order
-combinators generic layouts ;
+combinators generic layouts memoize ;
 IN: math.intervals
 
 SYMBOL: empty-interval
@@ -48,7 +48,10 @@ TUPLE: interval { from read-only } { to read-only } ;
 
 : (a,inf] ( a -- interval ) 1/0. (a,b] ; inline
 
-: [0,inf] ( -- interval ) 0 [a,inf] ; foldable
+MEMO: [0,inf] ( -- interval ) 0 [a,inf] ; foldable
+
+MEMO: fixnum-interval ( -- interval )
+    most-negative-fixnum most-positive-fixnum [a,b] ; inline
 
 : [-inf,inf] ( -- interval ) full-interval ; inline
 
@@ -331,12 +334,22 @@ SYMBOL: incomparable
     } cond
     swap 0 [a,a] interval>= t eq? [ [0,inf] interval-intersect ] when ;
 
+: (rem-range) ( i -- i' ) interval-abs to>> first 0 swap [a,b) ;
+
 : interval-rem ( i1 i2 -- i3 )
     {
         { [ over empty-interval eq? ] [ drop ] }
         { [ dup empty-interval eq? ] [ nip ] }
         { [ dup full-interval eq? ] [ nip ] }
-        [ nip interval-abs to>> first 0 swap [a,b) ]
+        [ (rem-range) 2dup interval-subset? [ drop ] [ nip ] if ]
+    } cond ;
+
+: interval->fixnum ( i1 -- i2 )
+    {
+        { [ dup empty-interval eq? ] [ ] }
+        { [ dup full-interval eq? ] [ drop fixnum-interval ] }
+        { [ dup fixnum-interval interval-subset? not ] [ drop fixnum-interval ] }
+        [ ]
     } cond ;
 
 : interval-bitand-pos ( i1 i2 -- ? )
index beb4aa89ac4f587f07b22c0deb700852619f33f8..1c855be1a485c84144538cdcc51eea63d683e04e 100644 (file)
@@ -74,6 +74,6 @@ SYNTAX: A{ \ } [ >A ] parse-literal ;
 
 INSTANCE: A sequence
 
-A T c-type class>> specialize-vector-words
+A T c-type-boxed-class specialize-vector-words
 
 ;FUNCTOR
diff --git a/extra/benchmark/yuv-to-rgb/yuv-to-rgb.factor b/extra/benchmark/yuv-to-rgb/yuv-to-rgb.factor
new file mode 100644 (file)
index 0000000..ca57de8
--- /dev/null
@@ -0,0 +1,95 @@
+! Copyright (C) Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.accessors alien.c-types alien.syntax byte-arrays
+destructors generalizations hints kernel libc locals math math.order
+sequences sequences.private ;
+IN: benchmark.yuv-to-rgb
+
+C-STRUCT: yuv_buffer
+    { "int" "y_width" }
+    { "int" "y_height" }
+    { "int" "y_stride" }
+    { "int" "uv_width" }
+    { "int" "uv_height" }
+    { "int" "uv_stride" }
+    { "void*" "y" }
+    { "void*" "u" }
+    { "void*" "v" } ;
+
+:: fake-data ( -- rgb yuv )
+    [let* | w [ 1600 ]
+            h [ 1200 ]
+            buffer [ "yuv_buffer" <c-object> ]
+            rgb [ w h * 3 * <byte-array> ] |
+        w buffer set-yuv_buffer-y_width
+        h buffer set-yuv_buffer-y_height
+        h buffer set-yuv_buffer-uv_height
+        w buffer set-yuv_buffer-y_stride
+        w buffer set-yuv_buffer-uv_stride
+        w h * [ dup * ] B{ } map-as malloc-byte-array &free buffer set-yuv_buffer-y
+        w h * 2/ [ dup dup * * ] B{ } map-as malloc-byte-array &free buffer set-yuv_buffer-u
+        w h * 2/ [ dup * dup * ] B{ } map-as malloc-byte-array &free buffer set-yuv_buffer-v
+        rgb buffer
+    ] ;
+
+: clamp ( n -- n )
+    255 min 0 max ; inline
+
+: stride ( line yuv  -- uvy yy )
+    [ yuv_buffer-uv_stride swap 2/ * >fixnum ]
+    [ yuv_buffer-y_stride * >fixnum ] 2bi ; inline
+
+: compute-y ( yuv uvy yy x -- y )
+    + >fixnum nip swap yuv_buffer-y swap alien-unsigned-1 16 - ; inline
+
+: compute-v ( yuv uvy yy x -- v )
+    nip 2/ + >fixnum swap yuv_buffer-u swap alien-unsigned-1 128 - ; inline
+
+: compute-u ( yuv uvy yy x -- v )
+    nip 2/ + >fixnum swap yuv_buffer-v swap alien-unsigned-1 128 - ; inline
+
+:: compute-yuv ( yuv uvy yy x -- y u v )
+    yuv uvy yy x compute-y
+    yuv uvy yy x compute-u
+    yuv uvy yy x compute-v ; inline
+
+: compute-blue ( y u v -- b )
+    drop 516 * 128 + swap 298 * + -8 shift clamp ; inline
+
+: compute-green ( y u v -- g )
+    [ [ 298 * ] dip 100 * - ] dip 208 * - 128 + -8 shift clamp ;
+    inline
+
+: compute-red ( y u v -- g )
+    nip 409 * swap 298 * + 128 + -8 shift clamp ; inline
+
+: compute-rgb ( y u v -- b g r )
+    [ compute-blue ] [ compute-green ] [ compute-red ] 3tri ;
+    inline
+
+: store-rgb ( index rgb b g r -- index )
+    [ pick 0 + pick set-nth-unsafe ]
+    [ pick 1 + pick set-nth-unsafe ]
+    [ pick 2 + pick set-nth-unsafe ] tri*
+    drop ; inline
+
+: yuv>rgb-pixel ( index rgb yuv uvy yy x -- index )
+    compute-yuv compute-rgb store-rgb 3 + >fixnum ; inline
+
+: yuv>rgb-row ( index rgb yuv y -- index )
+    over stride
+    pick yuv_buffer-y_width >fixnum
+    [ yuv>rgb-pixel ] with with with with each ; inline
+
+: yuv>rgb ( rgb yuv -- )
+    [ 0 ] 2dip
+    dup yuv_buffer-y_height >fixnum
+    [ yuv>rgb-row ] with with each
+    drop ;
+
+HINTS: yuv>rgb byte-array byte-array ;
+
+: yuv>rgb-benchmark ( -- )
+    [ fake-data yuv>rgb ] with-destructors ;
+
+MAIN: yuv>rgb-benchmark