1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* This is a much simpler version of UT_reduce.java that
18 * exercises pragmas after the functions (backward reference),
19 * whereas the other test case exercises the pragmas before the
20 * functions (forward reference).
21 */
22
23package com.android.rs.test;
24
25import android.content.Context;
26import android.content.res.Resources;
27import android.renderscript.*;
28import android.util.Log;
29import java.lang.Float;
30import java.util.Random;
31
32public class UT_reduce_backward extends UnitTest {
33    private static final String TAG = "reduce_backward";
34
35    protected UT_reduce_backward(RSTestCore rstc, Resources res, Context ctx) {
36        super(rstc, "reduce_backward", ctx);
37    }
38
39    private byte[] createInputArrayByte(int len, int seed) {
40        byte[] array = new byte[len];
41        (new Random(seed)).nextBytes(array);
42        return array;
43    }
44
45    private float[] createInputArrayFloat(int len, int seed) {
46        Random rand = new Random(seed);
47        float[] array = new float[len];
48        for (int i = 0; i < len; ++i)
49            array[i] = rand.nextFloat();
50        return array;
51    }
52
53    private int[] createInputArrayInt(int len, int seed) {
54        Random rand = new Random(seed);
55        int[] array = new int[len];
56        for (int i = 0; i < len; ++i)
57            array[i] = rand.nextInt();
58        return array;
59    }
60
61    private int[] createInputArrayInt(int len, int seed, int eltRange) {
62        Random rand = new Random(seed);
63        int[] array = new int[len];
64        for (int i = 0; i < len; ++i)
65            array[i] = rand.nextInt(eltRange);
66        return array;
67    }
68
69    private <T extends Number> boolean result(String testName, T javaRslt, T rsRslt) {
70        final boolean success = javaRslt.equals(rsRslt);
71        Log.i(TAG,
72                testName + ": java " + javaRslt + ", rs " + rsRslt + ": " +
73                (success ? "PASSED" : "FAILED"));
74        return success;
75    }
76
77    private boolean result(String testName, Float2 javaRslt, Float2 rsRslt) {
78        final boolean success = (javaRslt.x == rsRslt.x) && (javaRslt.y == rsRslt.y);
79        Log.i(TAG,
80                testName +
81                ": java (" + javaRslt.x + ", " + javaRslt.y + ")" +
82                ", rs (" + rsRslt.x + ", " + rsRslt.y + ")" +
83                ": " + (success ? "PASSED" : "FAILED"));
84        return success;
85    }
86
87    private boolean result(String testName, Int2 javaRslt, Int2 rsRslt) {
88        final boolean success = (javaRslt.x == rsRslt.x) && (javaRslt.y == rsRslt.y);
89        Log.i(TAG,
90                testName +
91                ": java (" + javaRslt.x + ", " + javaRslt.y + ")" +
92                ", rs (" + rsRslt.x + ", " + rsRslt.y + ")" +
93                ": " + (success ? "PASSED" : "FAILED"));
94        return success;
95    }
96
97    ///////////////////////////////////////////////////////////////////
98
99    private int addint(int[] input) {
100        int rslt = 0;
101        for (int idx = 0; idx < input.length; ++idx)
102            rslt += input[idx];
103        return rslt;
104    }
105
106    private boolean addint1D(RenderScript RS, ScriptC_reduce_backward s) {
107        final int[] input = createInputArrayInt(100000, 0, 1 << 13);
108
109        final int javaRslt = addint(input);
110        final int rsRslt = s.reduce_addint(input).get();
111
112        return result("addint1D", javaRslt, rsRslt);
113    }
114
115    private boolean addint2D(RenderScript RS, ScriptC_reduce_backward s) {
116        final int dimX = 450, dimY = 225;
117
118        final int[] inputArray = createInputArrayInt(dimX * dimY, 1, 1 << 13);
119        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
120        typeBuilder.setX(dimX).setY(dimY);
121        Allocation inputAllocation = Allocation.createTyped(RS, typeBuilder.create());
122        inputAllocation.copy2DRangeFrom(0, 0, dimX, dimY, inputArray);
123
124        final int javaRslt = addint(inputArray);
125        final int rsRslt = s.reduce_addint(inputAllocation).get();
126
127        return result("addint2D", javaRslt, rsRslt);
128    }
129
130    ///////////////////////////////////////////////////////////////////
131
132    private Int2 findMinAndMax(float[] input) {
133        float minVal = Float.POSITIVE_INFINITY;
134        int minIdx = -1;
135        float maxVal = Float.NEGATIVE_INFINITY;
136        int maxIdx = -1;
137
138        for (int idx = 0; idx < input.length; ++idx) {
139            if (input[idx] < minVal) {
140                minVal = input[idx];
141                minIdx = idx;
142            }
143            if (input[idx] > maxVal) {
144                maxVal = input[idx];
145                maxIdx = idx;
146            }
147        }
148
149        return new Int2(minIdx, maxIdx);
150    }
151
152    private boolean findMinAndMax(RenderScript RS, ScriptC_reduce_backward s) {
153        final float[] input = createInputArrayFloat(100000, 4);
154
155        final Int2 javaRslt = findMinAndMax(input);
156        final Int2 rsRslt = s.reduce_findMinAndMax(input).get();
157
158        // Note that the Java and RenderScript algorithms are not
159        // guaranteed to find the same cells -- but they should
160        // find cells of the same value.
161        final Float2 javaVal = new Float2(input[javaRslt.x], input[javaRslt.y]);
162        final Float2 rsVal = new Float2(input[rsRslt.x], input[rsRslt.y]);
163
164        return result("findMinAndMax", javaVal, rsVal);
165    }
166
167    ///////////////////////////////////////////////////////////////////
168
169    private boolean fz(RenderScript RS, ScriptC_reduce_backward s) {
170        final int inputLen = 100000;
171        int[] input = createInputArrayInt(inputLen, 5);
172        // just in case we got unlucky
173        input[(new Random(6)).nextInt(inputLen)] = 0;
174
175        final int rsRslt = s.reduce_fz(input).get();
176
177        final boolean success = (input[rsRslt] == 0);
178        Log.i(TAG,
179                "fz: input[" + rsRslt + "] == " + input[rsRslt] + ": " +
180                (success ? "PASSED" : "FAILED"));
181        return success;
182    }
183
184    ///////////////////////////////////////////////////////////////////
185
186    private boolean fz2(RenderScript RS, ScriptC_reduce_backward s) {
187        final int dimX = 225, dimY = 450;
188        final int inputLen = dimX * dimY;
189
190        int[] inputArray = createInputArrayInt(inputLen, 7);
191        // just in case we got unlucky
192        inputArray[(new Random(8)).nextInt(inputLen)] = 0;
193
194        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
195        typeBuilder.setX(dimX).setY(dimY);
196        Allocation inputAllocation = Allocation.createTyped(RS, typeBuilder.create());
197        inputAllocation.copy2DRangeFrom(0, 0, dimX, dimY, inputArray);
198
199        final Int2 rsRslt = s.reduce_fz2(inputAllocation).get();
200
201        final int cellVal = inputArray[rsRslt.x + dimX * rsRslt.y];
202        final boolean success = (cellVal == 0);
203        Log.i(TAG,
204                "fz2: input[" + rsRslt.x + ", " + rsRslt.y + "] == " + cellVal + ": " +
205                (success ? "PASSED" : "FAILED"));
206        return success;
207    }
208
209    ///////////////////////////////////////////////////////////////////
210
211    private boolean fz3(RenderScript RS, ScriptC_reduce_backward s) {
212        final int dimX = 59, dimY = 48, dimZ = 37;
213        final int inputLen = dimX * dimY * dimZ;
214
215        int[] inputArray = createInputArrayInt(inputLen, 9);
216        // just in case we got unlucky
217        inputArray[(new Random(10)).nextInt(inputLen)] = 0;
218
219        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
220        typeBuilder.setX(dimX).setY(dimY).setZ(dimZ);
221        Allocation inputAllocation = Allocation.createTyped(RS, typeBuilder.create());
222        inputAllocation.copy3DRangeFrom(0, 0, 0, dimX, dimY, dimZ, inputArray);
223
224        final Int3 rsRslt = s.reduce_fz3(inputAllocation).get();
225
226        final int cellVal = inputArray[rsRslt.x + dimX * rsRslt.y + dimX * dimY * rsRslt.z];
227        final boolean success = (cellVal == 0);
228        Log.i(TAG,
229                "fz3: input[" + rsRslt.x + ", " + rsRslt.y + ", " + rsRslt.z + "] == " + cellVal + ": " +
230                (success ? "PASSED" : "FAILED"));
231        return success;
232    }
233
234    ///////////////////////////////////////////////////////////////////
235
236    private static final int histogramBucketCount = 256;
237
238    private long[] histogram(RenderScript RS, final byte[] inputArray) {
239        Allocation inputAllocation = Allocation.createSized(RS, Element.U8(RS), inputArray.length);
240        inputAllocation.copyFrom(inputArray);
241
242        Allocation outputAllocation = Allocation.createSized(RS, Element.U32(RS), histogramBucketCount);
243
244        ScriptIntrinsicHistogram scriptHsg = ScriptIntrinsicHistogram.create(RS, Element.U8(RS));
245        scriptHsg.setOutput(outputAllocation);
246        scriptHsg.forEach(inputAllocation);
247
248        int[] outputArrayMistyped = new int[histogramBucketCount];
249        outputAllocation.copyTo(outputArrayMistyped);
250
251        long[] outputArray = new long[histogramBucketCount];
252        for (int i = 0; i < histogramBucketCount; ++i)
253            outputArray[i] = outputArrayMistyped[i] & (long)0xffffffff;
254        return outputArray;
255    }
256
257    private boolean histogram(RenderScript RS, ScriptC_reduce_backward s) {
258        final byte[] inputArray = createInputArrayByte(100000, 11);
259
260        final long[] javaRslt = histogram(RS, inputArray);
261        _RS_ASSERT("javaRslt unexpected length: " + javaRslt.length, javaRslt.length == histogramBucketCount);
262        final long[] rsRslt = s.reduce_histogram(inputArray).get();
263        _RS_ASSERT("rsRslt unexpected length: " + rsRslt.length, rsRslt.length == histogramBucketCount);
264
265        for (int i = 0; i < histogramBucketCount; ++i) {
266            if (javaRslt[i] != rsRslt[i]) {
267                Log.i(TAG,
268                        "histogram[" + i + "]: java " + javaRslt[i] + ", rs " + rsRslt[i] + ": FAILED");
269                return false;
270            }
271        }
272
273        Log.i(TAG, "histogram: PASSED");
274        return true;
275    }
276
277    //-----------------------------------------------------------------
278
279    private Int2 mode(RenderScript RS, final byte[] inputArray) {
280        long[] hsg = histogram(RS, inputArray);
281
282        int modeIdx = 0;
283        for (int i = 1; i < hsg.length; ++i)
284            if (hsg[i] > hsg[modeIdx]) modeIdx =i;
285        return new Int2(modeIdx, (int)hsg[modeIdx]);
286    }
287
288    private boolean mode(RenderScript RS, ScriptC_reduce_backward s) {
289        final byte[] inputArray = createInputArrayByte(100000, 12);
290
291        final Int2 javaRslt = mode(RS, inputArray);
292        final Int2 rsRslt = s.reduce_mode(inputArray).get();
293
294        return result("mode", javaRslt, rsRslt);
295    }
296
297    ///////////////////////////////////////////////////////////////////
298
299    public void run() {
300        RenderScript pRS = RenderScript.create(mCtx);
301        ScriptC_reduce_backward s = new ScriptC_reduce_backward(pRS);
302        s.set_negInf(Float.NEGATIVE_INFINITY);
303        s.set_posInf(Float.POSITIVE_INFINITY);
304
305        boolean pass = true;
306        pass &= addint1D(pRS, s);
307        pass &= addint2D(pRS, s);
308        pass &= findMinAndMax(pRS, s);
309        pass &= fz(pRS, s);
310        pass &= fz2(pRS, s);
311        pass &= fz3(pRS, s);
312        pass &= histogram(pRS, s);
313        pass &= mode(pRS, s);
314
315        pRS.finish();
316        pRS.destroy();
317
318        Log.i(TAG, pass ? "PASSED" : "FAILED");
319        if (pass)
320            passTest();
321        else
322            failTest();
323    }
324}
325