1 /*
2 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package hat.test;
26
27 import hat.Accelerator;
28 import hat.ComputeContext;
29 import hat.NDRange;
30 import hat.KernelContext;
31 import hat.backend.Backend;
32 import hat.buffer.S32Array;
33 import hat.buffer.S32Array2D;
34 import hat.ifacemapper.MappableIface.RO;
35 import hat.ifacemapper.MappableIface.RW;
36 import jdk.incubator.code.CodeReflection;
37 import hat.test.annotation.HatTest;
38 import hat.test.engine.HATAsserts;
39
40 import java.lang.invoke.MethodHandles;
41
42 public class TestMandel {
43
44 @CodeReflection
45 public static void mandel(@RO KernelContext kc, @RW S32Array2D s32Array2D, @RO S32Array pallette, float offsetx, float offsety, float scale) {
46 if (kc.gix < kc.gsx) {
47 float width = s32Array2D.width();
48 float height = s32Array2D.height();
49 float x = ((kc.gix % s32Array2D.width()) * scale - (scale / 2f * width)) / width + offsetx;
50 float y = ((kc.gix / s32Array2D.width()) * scale - (scale / 2f * height)) / height + offsety;
51 float zx = x;
52 float zy = y;
53 float new_zx;
54 int colorIdx = 0;
55 while ((colorIdx < pallette.length()) && (((zx * zx) + (zy * zy)) < 4f)) {
56 new_zx = ((zx * zx) - (zy * zy)) + x;
57 zy = (2f * zx * zy) + y;
58 zx = new_zx;
59 colorIdx++;
60 }
61 int color = colorIdx < pallette.length() ? pallette.array(colorIdx) : 0;
62 s32Array2D.array(kc.gix, color);
63 }
64 }
65
66 @CodeReflection
67 static public void compute(final ComputeContext computeContext, S32Array pallete, S32Array2D s32Array2D, float x, float y, float scale) {
68 NDRange ndRange = NDRange.of(NDRange.Global1D.of(s32Array2D.width() & s32Array2D.height()));
69 computeContext.dispatchKernel(ndRange,
70 kc -> {
71 TestMandel.mandel(kc, s32Array2D, pallete, x, y, scale);
72 });
73 }
74
75 public static void mandelSeq(@RW S32Array2D s32Array2D, @RO S32Array pallette, float offsetx, float offsety, float scale) {
76 for (int i = 0; i < pallette.length(); i++) {
77 float width = s32Array2D.width();
78 float height = s32Array2D.height();
79 float x = ((i % s32Array2D.width()) * scale - (scale / 2f * width)) / width + offsetx;
80 float y = (((float) i / s32Array2D.width()) * scale - (scale / 2f * height)) / height + offsety;
81 float zx = x;
82 float zy = y;
83 float new_zx;
84 int colorIdx = 0;
85 while ((colorIdx < pallette.length()) && (((zx * zx) + (zy * zy)) < 4f)) {
86 new_zx = ((zx * zx) - (zy * zy)) + x;
87 zy = (2f * zx * zy) + y;
88 zx = new_zx;
89 colorIdx++;
90 }
91 int color = colorIdx < pallette.length() ? pallette.array(colorIdx) : 0;
92 s32Array2D.array(i, color);
93 }
94
95 }
96
97 @HatTest
98 public void testMandel() {
99 Accelerator accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
100 final int width = 1024;
101 final int height = 1024;
102 final float defaultScale = 3f;
103 final float originX = -1f;
104 final float originY = 0;
105 final int maxIterations = 64;
106
107 S32Array2D s32Array2D = S32Array2D.create(accelerator, width, height);
108 S32Array2D check = S32Array2D.create(accelerator, width, height);
109
110 int[] palletteArray = new int[maxIterations];
111 for (int i = 1; i < maxIterations; i++) {
112 palletteArray[i]=(i/8+1);// 0-7?
113 }
114 palletteArray[0]=0;
115 S32Array pallette = S32Array.createFrom(accelerator, palletteArray);
116
117 accelerator.compute(cc -> TestMandel.compute(cc, pallette, s32Array2D, originX, originY, defaultScale));
118
119 // Check
120 TestMandel.mandelSeq(check, pallette, originX, originY, defaultScale);
121
122 int subsample = 16;
123 for (int y = 0; y<height/subsample; y++) {
124 for (int x = 0; x<width/subsample; x++) {
125 int palletteValue = s32Array2D.get(x * subsample, y * subsample); // so 0->8
126 int palletteValueSeq = s32Array2D.get(x * subsample, y * subsample); // so 0->8
127 HATAsserts.assertEquals(palletteValueSeq, palletteValue);
128 }
129 }
130 }
131 }