1 #include "shared.rsh" 2 3 // Same as reduce_backward.rs, except this test case places the 4 // pragmas before the functions (forward reference), and the other 5 // test case places the pragmas after the functions (backward 6 // reference). 7 8 float negInf, posInf; 9 10 ///////////////////////////////////////////////////////////////////////// 11 12 #pragma rs reduce(addint) \ 13 accumulator(aiAccum) 14 15 static void aiAccum(int *accum, int val) { *accum += val; } 16 17 ///////////////////////////////////////////////////////////////////////// 18 19 #pragma rs reduce(findMinAndMax) \ 20 initializer(fMMInit) accumulator(fMMAccumulator) \ 21 combiner(fMMCombiner) outconverter(fMMOutConverter) 22 23 typedef struct { 24 float val; 25 int idx; 26 } IndexedVal; 27 28 typedef struct { 29 IndexedVal min, max; 30 } MinAndMax; 31 32 static void fMMInit(MinAndMax *accum) { 33 accum->min.val = posInf; 34 accum->min.idx = -1; 35 accum->max.val = negInf; 36 accum->max.idx = -1; 37 } 38 39 static void fMMAccumulator(MinAndMax *accum, float in, int x) { 40 IndexedVal me; 41 me.val = in; 42 me.idx = x; 43 44 if (me.val < accum->min.val) 45 accum->min = me; 46 if (me.val > accum->max.val) 47 accum->max = me; 48 } 49 50 static void fMMCombiner(MinAndMax *accum, 51 const MinAndMax *val) { 52 if (val->min.val < accum->min.val) 53 accum->min = val->min; 54 if (val->max.val > accum->max.val) 55 accum->max = val->max; 56 } 57 58 static void fMMOutConverter(int2 *result, 59 const MinAndMax *val) { 60 result->x = val->min.idx; 61 result->y = val->max.idx; 62 } 63 64 ///////////////////////////////////////////////////////////////////////// 65 66 #pragma rs reduce(fz) \ 67 initializer(fzInit) \ 68 accumulator(fzAccum) combiner(fzCombine) 69 70 static void fzInit(int *accumIdx) { *accumIdx = -1; } 71 72 static void fzAccum(int *accumIdx, 73 int inVal, int x /* special arg */) { 74 if (inVal==0) *accumIdx = x; 75 } 76 77 static void fzCombine(int *accumIdx, const int *accumIdx2) { 78 if (*accumIdx2 >= 0) *accumIdx = *accumIdx2; 79 } 80 81 ///////////////////////////////////////////////////////////////////////// 82 83 #pragma rs reduce(fz2) \ 84 initializer(fz2Init) \ 85 accumulator(fz2Accum) combiner(fz2Combine) 86 87 static void fz2Init(int2 *accum) { accum->x = accum->y = -1; } 88 89 static void fz2Accum(int2 *accum, 90 int inVal, 91 int x /* special arg */, 92 int y /* special arg */) { 93 if (inVal==0) { 94 accum->x = x; 95 accum->y = y; 96 } 97 } 98 99 static void fz2Combine(int2 *accum, const int2 *accum2) { 100 if (accum2->x >= 0) *accum = *accum2; 101 } 102 103 ///////////////////////////////////////////////////////////////////////// 104 105 #pragma rs reduce(fz3) \ 106 initializer(fz3Init) \ 107 accumulator(fz3Accum) combiner(fz3Combine) 108 109 static void fz3Init(int3 *accum) { accum->x = accum->y = accum->z = -1; } 110 111 static void fz3Accum(int3 *accum, 112 int inVal, 113 int x /* special arg */, 114 int y /* special arg */, 115 int z /* special arg */) { 116 if (inVal==0) { 117 accum->x = x; 118 accum->y = y; 119 accum->z = z; 120 } 121 } 122 123 static void fz3Combine(int3 *accum, const int3 *accum2) { 124 if (accum->x >= 0) *accum = *accum2; 125 } 126 127 ///////////////////////////////////////////////////////////////////////// 128 129 #pragma rs reduce(histogram) \ 130 accumulator(hsgAccum) combiner(hsgCombine) 131 132 #define BUCKETS 256 133 typedef uint32_t Histogram[BUCKETS]; 134 135 static void hsgAccum(Histogram *h, uchar in) { ++(*h)[in]; } 136 137 static void hsgCombine(Histogram *accum, const Histogram *addend) { 138 for (int i = 0; i < BUCKETS; ++i) 139 (*accum)[i] += (*addend)[i]; 140 } 141 142 #pragma rs reduce(mode) \ 143 accumulator(hsgAccum) combiner(hsgCombine) \ 144 outconverter(modeOutConvert) 145 146 static void modeOutConvert(int2 *result, const Histogram *h) { 147 uint32_t mode = 0; 148 for (int i = 1; i < BUCKETS; ++i) 149 if ((*h)[i] > (*h)[mode]) mode = i; 150 result->x = mode; 151 result->y = (*h)[mode]; 152 } 153