AKTIVE

by-rows.tcl at trunk
Login

by-rows.tcl at trunk

File etc/transformer/statistics/by-rows.tcl artifact 14394d322d on branch trunk


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
   100
   101
   102
   103
   104
   105
## -*- mode: tcl ; fill-column: 90 -*-
# # ## ### ##### ######## ############# #####################
## Transformers -- Statistics by rows.

# # ## ### ##### ######## ############# #####################
## Compress rows down to a statistic

operator {dexpr attr} {
    op::row::arg::max    {first index}        maximal
    op::row::arg::min    {first index}        minimal
    op::row::max         maximum              {}
    op::row::mean        {arithmetic mean}    {}
    op::row::min         minimum              {}
    op::row::profile     {left profile}       {}
    op::row::rprofile    {right profile}      {}
    op::row::stddev      {standard deviation} {}
    op::row::sum         sum                  {}
    op::row::sumsquared  sum                  squared
    op::row::variance    variance             {}
} {
    op -> _ kind fun extra
    if {$fun eq "arg"} { def fun $fun$extra }

    set int [expr {$fun in {mean stddev variance} ? "" : "-int"}]
    example [string map [list INT $int] {
	aktive op sdf 2image smooth [aktive op sdf ring [aktive image sdf triangle width 32 height 32 a {10 10} b {50 80} c {80 30}] thickness 4]
	@1 | -matrix INT
    }]
    unset int

    section transform statistics

    ## simplifications (also apply for input width == 1)
    #
    ## - arg::max   :: const 0 (single value is max, at index 0)
    ## - arg::min   :: const 0 (single value is min, at index 0)
    ## - max        :: elide (idempotent / identity)
    ## - mean       :: elide (idempotent / identity)
    ## - min        :: elide (idempotent / identity)
    ## - stddev     :: const 0
    ## - sum        :: elide (idempotent / identity)
    ## - sumsquared :: op math1 pow 2 (power chaining)
    ## - variance   :: const 0
    ## - profile    :: NONE
    ## - rprofile   :: NONE

    import? ../simpler/stat_$fun.rules	;# queries kind !!

    note Returns image with input rows compressed to a single value, \
	the $dexpr of the {*}$attr row values. The result is a single-column \
	image with height and depth of the input.

    note The bands of a multi-band image are processed separately.

    switch -exact -- $fun {
	profile {
	    note The __left__ profile of each row is the index of the \
		__first__ column with a __non-zero__ value. Or the \
		width of the image, if there are no such in the row.
	}
	rprofile {
	    note The __right__ profile of each row is the index of the \
		__last__ column with a __non-zero__ value. Or `-1`, if \
		there are no such in the row.
	}
    }

    input

    state -fields {
	aktive_uint width; // quick access to input width
    } -setup {
	aktive_geometry_copy (domain, aktive_image_get_geometry (srcs->v[0]));
	state->width = domain->width;
	domain->width = 1;
    }

    # AW == 1. We care about AX here. (Single iteration "loop")
    blit reducer {
	{AH {y AY 1 up} {y 0 1 up}}
	{ 1 {x AX 1 up} {x 0 1 up}}
    } {raw reduce-row {
	// dstvalue = row/band start -
	// srcvalue = row/band start - SD-strided row vector
	REDUCE (dstvalue, srcvalue, SW, SD); // dstvalue, srcvalue :: row start
    }}
    ## __UNROLL__ option1: compute all bands together (1/2/3/many specialization)
    ## __UNROLL__ note: differs from by-band in the scope of the aggregation

    pixels {
	aktive_rectangle_def_as (subrequest, request);
        // always fetch the entire row of the source ...
	subrequest.width = istate->width;
	TRACE_RECTANGLE_M("@@fun@@", &subrequest);
	aktive_block* src = aktive_region_fetch_area (0, &subrequest);
        // ... and reduce
	#define REDUCE aktive_reduce_rows_@@fun@@
	@@reducer@@
	#undef REDUCE
    }
}

##
# # ## ### ##### ######## ############# #####################
::return