scheduling common loop in discreet pipeline funcs - halide

I have a number of halide pipelines (lowercase p) which all read the same input image and produce unique outputs. Some share common output dimensions, some do not. Every pipeline reads each pixel in the source image once. The output images needed may vary at runtime based on user input.
I'm using a Pipeline to compute all of these outputs into a Realization. Is there any way to schedule these disparate Funcs to achieve a single outer loop in the Pipeline?
It appears I can create a wrapper function which packs these Funcs into a Tuple and but this requires they all output the same dimensions.
Am I missing any other options?
Edited to Add Sample code
//Buffer<> input = Buffer<uint8_t>::make_interleaved(width, height, 4);
//fill buffer with image data
Var x("x"), y("y"), c("c");
Func rgb("rgb");
rgb(x,y,c) = ConciseCasts::u8_sat(input(x,y,c));
// Define a one-dimensional reduction domain over x
RDom r(0, input.width());
Func hist1("hist1");
Func hist2("hist2");
// Histogram buckets start as zero.
hist1(x,y) = 0;
hist2(x,y,c) = 0;
// Make a histogram for every scanline of input
hist1(rgb(r, y, 0), y ) += 1;
hist2(rgb(r, y, c), y, c) += 1;
Func clamp1("clamp1");
clamp1(x,y) = ConciseCasts::u8_sat(hist1(x,y));
Func clamp2("clamp2");
clamp2(x,y,c) = ConciseCasts::u8_sat(hist2(x,y,c));
//use clamp1 as a wrapper
hist1.compute_at(clamp1, y);
//schedule hist2 the same way (but unroll c)
hist2.compute_at(clamp2, y);
clamp2.bound(c,0,3).reorder(c, x, y).unroll(c);
hist2.bound(c,0,3).reorder(c, x, y).unroll(c);
hist2.update(0).reorder(c, r, y).unroll(c);
clamp1
.bound(x, 0, 256)
.bound(y, 0, input.height());
clamp2
.bound(x, 0, 256)
.bound(y, 0, input.height());
Pipeline pipe = Pipeline({clamp1, clamp2});
Looking at the lowered statement I see:
produce clamp1 {
for (clamp1.s0.y, 0, 2160) {
allocate hist1[int32 * 256 * 1]
produce hist1 {
for (hist1.s0.x, 0, 256) {
hist1[hist1.s0.x] = 0
}
for (hist1.s1.r4$x, 0, 4096) {
hist1[int32(b0[((hist1.s1.r4$x*4) + (clamp1.s0.y*16384))])] = (hist1[int32(b0[((hist1.s1.r4$x*4) + (clamp1.s0.y*16384))])] + 1)
}
}
for (clamp1.s0.x, 0, 256) {
clamp1[((clamp1.s0.x + (clamp1.s0.y*clamp1.stride.1)) - (clamp1.min.0 + (clamp1.min.1*clamp1.stride.1)))] = uint8(max(min(hist1[clamp1.s0.x], 255), 0))
}
free hist1
}
}
produce clamp2 {
for (clamp2.s0.y, 0, 2160) {
allocate hist2[int32 * 256 * 1 * 3]
produce hist2 {
for (hist2.s0.x, 0, 256) {
hist2[hist2.s0.x] = 0
hist2[(hist2.s0.x + 256)] = 0
hist2[(hist2.s0.x + 512)] = 0
}
for (hist2.s1.r4$x, 0, 4096) {
hist2[int32(b0[((hist2.s1.r4$x*4) + (clamp2.s0.y*16384))])] = (hist2[int32(b0[((hist2.s1.r4$x*4) + (clamp2.s0.y*16384))])] + 1)
hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 1)]) + 256)] = (hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 1)]) + 256)] + 1)
hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 2)]) + 512)] = (hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 2)]) + 512)] + 1)
}
}
for (clamp2.s0.x, 0, 256) {
clamp2[((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[clamp2.s0.x], 255), 0))
clamp2[(((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) + clamp2.stride.2) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[(clamp2.s0.x + 256)], 255), 0))
clamp2[(((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) + (clamp2.stride.2*2)) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[(clamp2.s0.x + 512)], 255), 0))
}
free hist2
}
}
}
What I'm hoping to achieve is a lowered statement that looks closer to this (I just cut and pasted this together):
produce clamps {
for (clamp1.s0.y, 0, 2160) {
allocate hist1[int32 * 256 * 1]
allocate hist2[int32 * 256 * 1 * 3]
produce hists {
for (hist1.s0.x, 0, 256) {
hist1[hist1.s0.x] = 0
hist2[hist2.s0.x] = 0
hist2[(hist2.s0.x + 256)] = 0
hist2[(hist2.s0.x + 512)] = 0
}
for (hist1.s1.r4$x, 0, 4096) {
hist1[int32(b0[((hist1.s1.r4$x*4) + (clamp1.s0.y*16384))])] = (hist1[int32(b0[((hist1.s1.r4$x*4) + (clamp1.s0.y*16384))])] + 1)
hist2[int32(b0[((hist2.s1.r4$x*4) + (clamp2.s0.y*16384))])] = (hist2[int32(b0[((hist2.s1.r4$x*4) + (clamp2.s0.y*16384))])] + 1)
hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 1)]) + 256)] = (hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 1)]) + 256)] + 1)
hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 2)]) + 512)] = (hist2[(int32(b0[(((hist2.s1.r4$x*4) + (clamp2.s0.y*16384)) + 2)]) + 512)] + 1)
}
}
for (clamp1.s0.x, 0, 256) {
clamp1[((clamp1.s0.x + (clamp1.s0.y*clamp1.stride.1)) - (clamp1.min.0 + (clamp1.min.1*clamp1.stride.1)))] = uint8(max(min(hist1[clamp1.s0.x], 255), 0))
clamp2[((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[clamp2.s0.x], 255), 0))
clamp2[(((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) + clamp2.stride.2) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[(clamp2.s0.x + 256)], 255), 0))
clamp2[(((clamp2.s0.x + (clamp2.s0.y*clamp2.stride.1)) + (clamp2.stride.2*2)) - ((clamp2.min.0 + (clamp2.min.1*clamp2.stride.1)) + (clamp2.min.2*clamp2.stride.2)))] = uint8(max(min(hist2[(clamp2.s0.x + 512)], 255), 0))
}
free hist1
free hist2
}
}
However if I try to add
clamp2.compute_with(clamp1, y);
I get the following error when jitting
Internal error at /Halide/src/ScheduleFunctions.cpp:2228
Condition failed: injector.found_store_level && injector.found_compute_level

This might be another use case for compute_with, which is not merged yet. You can try out the compute_with_directive branch to see if it meets your needs. Hopefully this will be merged soon.

Related

When creating an angle, how do I control the attributes of the automatically created points?

I'm working with a polygon and attempting to create angles with labels but when angles are created, so are the points used to define them. This would be fine but I can't control the labels on the automatically created points (and I don't know what they are called or how to find out).
var points = [
[0, 0],
[0, 5],
[3, 0]
];
for (k = 0; k < showAngle.length; k++) {
if (showAngle[k] == 1) {
var angle = board.create('angle', [points[k], points[((k + 1) % points.length)], points[((k + 2) % points.length)]],{fixed:true});
} else if (showAngle[k] == 2) {
var angle = board.create('angle', [points[k], points[((k + 1) % points.length)], points[((k + 2) % points.length)]], {
fixed: false,
name: function() {
return ((180/Math.PI)*JXG.Math.Geometry.rad(points[k], points[((k + 1) % points.length)], points[((k + 2) % points.length)])).toFixed(1) + '°';
}
});
}
}
https://jsfiddle.net/jscottuq/acyrLxfh/12/ contains what I've got so far.
The arrays showLen and showAngle are setting what labels are shown for each side/angle (0 - no label, 1 - name , 2 - measurement).
These will be set when the jsxgraph is created.
At the time being, the possibility to control the style of the newly created points of an angle is missing. We will add this soon.
However, a solution would be to use the already existing points which are hidden in this example. For this it would be helpful to kee a list of these points, e.g. jxg_points:
var jxg_points = [];
for (i = 0; i < points.length; i++) {
var rise = points[(i + 1) % points.length][1] - points[i][1];
var run = points[(i + 1) % points.length][0] - points[i][0];
var point = board.create('point', [points[i][0], points[i][1]], {
fixed: true,
visible:false
});
jxg_points.push(point); // Store the point
points[i].pop();
len[i] = Math.round((Math.sqrt(rise * rise + run * run) + Number.EPSILON) * 100) / 100;
}
Then the points can be reused for the angles without creating new points:
for (k = 0; k < showAngle.length; k++) {
if (showAngle[k] == 1) {
angle = board.create('angle', [
jxg_points[k],
jxg_points[((k + 1) % jxg_points.length)],
jxg_points[((k + 2) % jxg_points.length)]
],{fixed:true});
} else if (showAngle[k] == 2) {
var angle = board.create('angle', [
jxg_points[k],
jxg_points[((k + 1) % jxg_points.length)],
jxg_points[((k + 2) % jxg_points.length)]], {
fixed: false,
name: function() {
return ((180/Math.PI)*JXG.Math.Geometry.rad(points[k], points[((k + 1) % points.length)], points[((k + 2) % points.length)])).toFixed(1) + '°';
}
});
}
}
See it live at https://jsfiddle.net/d8an0epy/.

Halide JIT vs Generator Differences

While playing around with Halide, I see that totally different pseudocodes are created for a same pipline when using JIT and a generated function approaches. It looks like I'm missing something and so I'd very appreciate and hint. Here is what I did:
A simple 'dilate' pipline is defined as:
int jit_main ()
{
Target target = get_jit_target_from_environment ();
const int width = 1280, height = 1024;
Buffer <uint8_t> input (width, height);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
input (x, y) = rand () & 0xff;
Var x ("x_1"), y ("y_1");
Func clamped ("clamped_1");
clamped = BoundaryConditions::repeat_edge (input);
Func max_x ("max_x_1");
max_x (x, y) = max (clamped (x - 1, y), clamped (x, y), clamped (x + 1, y));
Func dilate ("dilate_1");
dilate (x, y) = max (max_x (x, y - 1), max_x (x, y), max_x (x, y + 1));
tick (NULL);
Buffer<uint8_t> out = dilate.realize (width, height, target);
tick ("inline");
dilate.print_loop_nest ();
dilate.compile_to_lowered_stmt ("dilate_1_.html", {}, HTML);
}
The resulting pseudocode looks as follows (fragment):
produce dilate_1 {
let t125 = ((dilate_1.min.1 * dilate_1.stride.1) + dilate_1.min.0)
for (dilate_1.s0.y_1, dilate_1.min.1, dilate_1.extent.1) {
let t128 = max(min(dilate_1.s0.y_1, 1024), 1)
let t126 = max(min(dilate_1.s0.y_1, 1023), 0)
let t127 = max(min(dilate_1.s0.y_1, 1022), -1)
let t129 = ((dilate_1.s0.y_1 * dilate_1.stride.1) - t125)
for (dilate_1.s0.x_1, dilate_1.min.0, dilate_1.extent.0) {
dilate_1[(dilate_1.s0.x_1 + t129)] = max(b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t126 * 1280)) + 1)], max(b0[(max(min(dilate_1.s0.x_1, 1279), 0) + (t126 * 1280))], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t126 * 1280)) + -1)], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t127 * 1280)) + 1279)], max(b0[((max(min(dilate_1.s0.x_1, 1279), 0) + (t127 * 1280)) + 1280)], max(b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t127 * 1280)) + 1281)], max(b0[((max(min(dilate_1.s0.x_1, 1280), 1) + (t128 * 1280)) + -1281)], max(b0[((max(min(dilate_1.s0.x_1, 1279), 0) + (t128 * 1280)) + -1280)], b0[((max(min(dilate_1.s0.x_1, 1278), -1) + (t128 * 1280)) + -1279)]))))))))
}
}
}
Then I defined a generator:
class Dilate0Generator : public Halide::Generator <Dilate0Generator>
{
public:
Input<Buffer<uint8_t>> input_0 {"input_0", 2};
Output<Buffer<uint8_t>> dilate_0 {"dilate_0", 2};
Var x {"x_0"}, y {"y_0"};
void generate ()
{
Func clamped_0 {"clamped_0"};
clamped_0 = BoundaryConditions::repeat_edge (input_0);
Func max_x_0 {"max_x_0"};
max_x_0 (x, y) =
max (clamped_0 (x - 1, y), clamped_0 (x, y), clamped_0 (x + 1, y));
dilate_0 (x, y) =
max (max_x_0 (x, y - 1), max_x_0 (x, y), max_x_0 (x, y + 1));
dilate_0.print_loop_nest ();
}
};
HALIDE_REGISTER_GENERATOR (Dilate0Generator, dilate_0)
And it's pseudocode is completely different (fragment):
produce dilate_0 {
let dilate_0.s0.y_0.prologue = min(max((input_0.min.1 + 1), dilate_0.min.1), (dilate_0.extent.1 + dilate_0.min.1))
let dilate_0.s0.y_0.epilogue$3 = min(max(max((input_0.min.1 + 1), dilate_0.min.1), ((input_0.extent.1 + input_0.min.1) + -1)), (dilate_0.extent.1 + dilate_0.min.1))
let t166 = (dilate_0.s0.y_0.prologue - dilate_0.min.1)
let t168 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t170 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
let t167 = (input_0.extent.1 + input_0.min.1)
let t169 = (input_0.extent.0 + input_0.min.0)
for (dilate_0.s0.y_0, dilate_0.min.1, t166) {
let t171 = ((max(min((t167 + -1), dilate_0.s0.y_0), input_0.min.1) * input_0.stride.1) - t168)
let t173 = ((max((min((dilate_0.s0.y_0 + 2), t167) + -1), input_0.min.1) * input_0.stride.1) - t168)
let t174 = ((max((min(dilate_0.s0.y_0, t167) + -1), input_0.min.1) * input_0.stride.1) - t168)
let t175 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t170)
for (dilate_0.s0.x_0, dilate_0.min.0, dilate_0.extent.0) {
dilate_0[(dilate_0.s0.x_0 + t175)] = (let t132 = max((min((dilate_0.s0.x_0 + 2), t169) + -1), input_0.min.0) in (let t133 = max(min((t169 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t134 = max((min(dilate_0.s0.x_0, t169) + -1), input_0.min.0) in max(input_0[(t132 + t171)], max(input_0[(t133 + t171)], max(input_0[(t134 + t171)], max(input_0[(t134 + t173)], max(input_0[(t133 + t173)], max(input_0[(t132 + t173)], max(input_0[(t134 + t174)], max(input_0[(t133 + t174)], input_0[(t132 + t174)])))))))))))
}
}
let t183 = (dilate_0.extent.0 + dilate_0.min.0)
let t184 = (input_0.extent.0 + input_0.min.0)
let t185 = max((input_0.min.0 + 1), dilate_0.min.0)
let t178 = min(max((t184 + -1), t185), t183)
let t177 = min(t183, t185)
let t176 = (dilate_0.s0.y_0.epilogue$3 - dilate_0.s0.y_0.prologue)
let t179 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t181 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
for (dilate_0.s0.y_0, dilate_0.s0.y_0.prologue, t176) {
let t189 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t190 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t187 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t191 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t186 = (t177 - dilate_0.min.0)
for (dilate_0.s0.x_0, dilate_0.min.0, t186) {
dilate_0[(dilate_0.s0.x_0 + t191)] = (let t140 = max((min((dilate_0.s0.x_0 + 2), t184) + -1), input_0.min.0) in (let t141 = max(min((t184 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t142 = max((min(dilate_0.s0.x_0, t184) + -1), input_0.min.0) in max(input_0[(t140 + t187)], max(input_0[(t141 + t187)], max(input_0[(t142 + t187)], max(input_0[(t142 + t189)], max(input_0[(t141 + t189)], max(input_0[(t140 + t189)], max(input_0[(t142 + t190)], max(input_0[(t141 + t190)], input_0[(t140 + t190)])))))))))))
}
let t194 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t195 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t193 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t196 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t192 = (t178 - t177)
for (dilate_0.s0.x_0, t177, t192) {
dilate_0[(dilate_0.s0.x_0 + t196)] = max(input_0[((dilate_0.s0.x_0 + t193) + 1)], max(input_0[(dilate_0.s0.x_0 + t193)], max(input_0[((dilate_0.s0.x_0 + t193) + -1)], max(input_0[((dilate_0.s0.x_0 + t194) + -1)], max(input_0[(dilate_0.s0.x_0 + t194)], max(input_0[((dilate_0.s0.x_0 + t194) + 1)], max(input_0[((dilate_0.s0.x_0 + t195) + -1)], max(input_0[(dilate_0.s0.x_0 + t195)], input_0[((dilate_0.s0.x_0 + t195) + 1)]))))))))
}
let t200 = (((dilate_0.s0.y_0 + 1) * input_0.stride.1) - t179)
let t201 = (((dilate_0.s0.y_0 + -1) * input_0.stride.1) - t179)
let t198 = ((dilate_0.s0.y_0 * input_0.stride.1) - t179)
let t202 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t181)
let t197 = (t183 - t178)
for (dilate_0.s0.x_0, t178, t197) {
dilate_0[(dilate_0.s0.x_0 + t202)] = (let t152 = max((min((dilate_0.s0.x_0 + 2), t184) + -1), input_0.min.0) in (let t153 = max(min((t184 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t154 = max((min(dilate_0.s0.x_0, t184) + -1), input_0.min.0) in max(input_0[(t152 + t198)], max(input_0[(t153 + t198)], max(input_0[(t154 + t198)], max(input_0[(t154 + t200)], max(input_0[(t153 + t200)], max(input_0[(t152 + t200)], max(input_0[(t154 + t201)], max(input_0[(t153 + t201)], input_0[(t152 + t201)])))))))))))
}
}
let t203 = ((dilate_0.extent.1 + dilate_0.min.1) - dilate_0.s0.y_0.epilogue$3)
let t205 = ((input_0.min.1 * input_0.stride.1) + input_0.min.0)
let t207 = ((dilate_0.min.1 * dilate_0.stride.1) + dilate_0.min.0)
let t204 = (input_0.extent.1 + input_0.min.1)
let t206 = (input_0.extent.0 + input_0.min.0)
for (dilate_0.s0.y_0, dilate_0.s0.y_0.epilogue$3, t203) {
let t208 = ((max(min((t204 + -1), dilate_0.s0.y_0), input_0.min.1) * input_0.stride.1) - t205)
let t210 = ((max((min((dilate_0.s0.y_0 + 2), t204) + -1), input_0.min.1) * input_0.stride.1) - t205)
let t211 = ((max((min(dilate_0.s0.y_0, t204) + -1), input_0.min.1) * input_0.stride.1) - t205)
let t212 = ((dilate_0.s0.y_0 * dilate_0.stride.1) - t207)
for (dilate_0.s0.x_0, dilate_0.min.0, dilate_0.extent.0) {
dilate_0[(dilate_0.s0.x_0 + t212)] = (let t161 = max((min((dilate_0.s0.x_0 + 2), t206) + -1), input_0.min.0) in (let t162 = max(min((t206 + -1), dilate_0.s0.x_0), input_0.min.0) in (let t163 = max((min(dilate_0.s0.x_0, t206) + -1), input_0.min.0) in max(input_0[(t161 + t208)], max(input_0[(t162 + t208)], max(input_0[(t163 + t208)], max(input_0[(t163 + t210)], max(input_0[(t162 + t210)], max(input_0[(t161 + t210)], max(input_0[(t163 + t211)], max(input_0[(t162 + t211)], input_0[(t161 + t211)])))))))))))
}
}
}
The generated version runs in an order of magnitude faster, which is not surprising, given that the pseudocode for it looks a lot more optimized.
It runs even faster that an existed example
My noob question is how comes that JIT can not create the same representation?
Thanks a lot for any answer/idea/help/hint...
The difference between the two is that in the JIT case, the size of the input (and thus the location of the boundary condition) is known at compile-time.
However the generated code should be similar. I think the fact that you don't get five separate cases in the JIT case is a bug in Halide. I have opened an issue on the Halide github repo.
https://github.com/halide/Halide/issues/5353
EDIT: Thanks for uncovering a bug! Fixed in https://github.com/halide/Halide/pull/5355

How can I optimise my code using "For-Loop"?

I am trying to develop a code which calculates Local Density of states of electrons in a material. For which I am using a multiple for loops and multiple tables. it takes 45sec to complete, I need less time for that. any suggestions how to optimize this code.
AbsoluteTiming[Ns=2; \[Eta] = 0.001;
Nx=15;
Ny=15;
NN=Nx*Ny;
Nband=8;
kkmx = Ns*Nx;
kkmy = Ns*Ny;
wmax = 0.2; nw = 800; p = 0;
Print["starting ldos calc"];
nsite = 2;
ldos = 0;
For[kx = 0, kx <= (Ns - 1.)*2*(Pi/kkmx), kx += 2*(Pi/kkmx),
For[ky = 0, ky <= (Ns - 1.)*2*(Pi/kkmy), ky += 2*(Pi/kkmy),
ES = Eigensystem[H];
elist = Table[ES[[1,l]], {l, 1, Nband/2*4*NN}];
ulist = Table[Abs[ES[[2,l,i]]]^2, {l, 1, Nband/2*4*NN}, {i, 388+1, 388+(nsite - 1)*Nband/2 + Nband/2}];
vlist = Table[Abs[ES[[2,l,i + Nband/2*NN*2]]]^2, {l, 1, Nband/2*4*NN}, {i, 388+1, 388+(nsite - 1)*Nband/2 + Nband/2}];
ldossc = Table[Im[Total[Table[ulist[[l,1 ;; All]]*(1/(-wmax + wmax*2*(w/nw) - elist[[l]] + I*\[Eta])) +
vlist[[l,1 ;; All]]*(1/(-wmax + 2*wmax*(w/nw) + elist[[l]] + I*\[Eta])), {l, 1, Nband/2*4*NN}]]], {w, 0, nw}]; ldos = ldos + ldossc;
Export["ldosorb_up_P.dat", Table[{-wmax + wmax*2*(\[Omega]/nw), (-Pi^(-1))*(ldos[[\[Omega] + 1,i]]/Ns^2)}, {\[Omega], 0, nw}, {i, 1,8}]];
(* Export["ldostot.dat", Table[{-wmax + wmax*2*(\[Omega]/nw), (-Pi^(-1))*((ldos[[\[Omega] + 1,i]] + ldos[[\[Omega] + 1,i + 1]] + ldos[[\[Omega] + 1,i + 2]] + ldos[[\[Omega] + 1,i + 3]] + ldos[[\[Omega] + 1,i + 4]])/Ns^2)}, {\[Omega], 0, nw}, {i, 1, (nsite - 1)*Nband/2 + Nband/2 - 4}]]; *)
Print["kx=", kx, " ky=", ky, " nsx=", (kx/(2*Pi))*kkmx + 1.]; ]; ]; ]```

Scala implementation of sobel filter

I'm looking for some help in a IT school project. We need to create a programm which can detect roads in a satelite photograph. Our group decided to use a function for detect edges. We search differents solutions and filters on Internet and we decides to use Sobel filter.
We have tried to implement this filter in Scala but it didn't work. We use differents webpages to help us, some of these are on StackOverflow (here). We use this one to help us and try to translate the code : Sobel filter in Ruby.
Start Code --
codeGrey(); // This function transform the RGB in grey level
var sobel_x: Array[Array[Double]] = Array(
Array(-1, 0, 1),
Array(-2, 0, 2),
Array(-1, 0, 1))
var sobel_y: Array[Array[Double]] = Array(
Array(1, 2, 1),
Array(0, 0, 0),
Array(-1, -2, 1))
for (x <- 1 to wrappedImage.height - 2) {
for (y <- 1 to wrappedImage.width - 2) {
var a = (image2D(x - 1)(y - 1) & 0x00FF0000) >> 16
var b = (image2D(x)(y - 1) & 0x00FF0000) >> 16
var c = (image2D(x + 1)(y - 1) & 0x00FF0000) >> 16
var d = (image2D(x - 1)(y) & 0x00FF0000) >> 16
var e = (image2D(x)(y) & 0x00FF0000) >> 16
var f = (image2D(x + 1)(y) & 0x00FF0000) >> 16
var g = (image2D(x - 1)(y + 1) & 0x00FF0000) >> 16
var h = (image2D(x)(y + 1) & 0x00FF0000) >> 16
var i = (image2D(x + 1)(y + 1) & 0x00FF0000) >> 16
var pixel_x =
(sobel_x(0)(0) * a) + (sobel_x(0)(1) * b) + (sobel_x(0)(2) * c) +
(sobel_x(1)(0) * d) + (sobel_x(1)(1) * e) + (sobel_x(1)(2) * f) +
(sobel_x(2)(0) * g) + (sobel_x(2)(1) * h) + (sobel_x(2)(2) * i);
var pixel_y =
(sobel_y(0)(0) * a) + (sobel_x(0)(1) * b) + (sobel_x(0)(2) * c) +
(sobel_y(1)(0) * d) + (sobel_x(1)(1) * e) + (sobel_x(1)(2) * f) +
(sobel_y(2)(0) * g) + (sobel_x(2)(1) * h) + (sobel_x(2)(2) * i);
var res = (Math.sqrt((pixel_x * pixel_x) + (pixel_y * pixel_y)).ceil).toInt
image2D(x)(y) = 0xFF000000 + (res * 65536 + res * 256 + res);
}
}
End Code --
The image returned by this implementation is just an image with black and white pixels and I don't know why. I've got no experience in image processing and we learned Scala 8 weeks ago so that doesn't help.
I'm sorry, my english is not perfect so please forgive me if I didn't write correctly.
I'm not sure I grasp all the details of your solution, anyway here some observation:
consider using vals instead of vars: Scala prefers
immutables and you are not really changing any of those variables.
In scala you can write nested for cycles as a single one over two
variables (check here for details:
Nested iteration in Scala). I think it makes code cleaner.
I presume image2D is the array of arrays in which you are
holding your image. In the last line of your nested for loop you are
changing the current pixel value. This is not good because you will
access that same pixel later when you calculate your a,b,..,h,i
values. The center pixel during current iteration is the side pixel
during next iteration. I think you should write the result in a
different matrix.

EAN 8 : How to calculate checksum digit?

I need to create EAN 8 bar code programmatically.
I search an algorithm to calculate the checksum digit.
The algorithm is covered in this wikipedia article on EAN, note that EAN-8 is calculated in the same way as EAN-13.
Here's a worked example from http://www.barcodeisland.com/ean8.phtml :
Assuming we wish to encode the 7-digit message "5512345", we would calculate the checksum in the following manner:
Barcode 5 5 1 2 3 4 5
Odd/Even Pos? O E O E O E O
Weighting 3 1 3 1 3 1 3
Calculation 5*3 5*1 1*3 2*1 3*3 4*1 5*3
Weighted Sum 15 5 3 2 9 4 15
The total is 15 + 5 + 3 + 2 + 9 + 4 + 15 = 53. 7 must be added to 53 to produce a number evenly divisible by 10, thus the checksum digit is 7 and the completed bar code value is "55123457".
string code="55123457";
int sum1 = code[1] + code[3] + code[5]
int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
int checksum_value = sum1 + sum2;
int checksum_digit = 10 - (checksum_value % 10);
if (checksum_digit == 10)
checksum_digit = 0;
int checkSum(const std::vector<int>& code) const
{
if (code.size() < 8) return false;
for( SIZE_T i = 0; i< code.size(); i++ )
{
if( code[i] < 0 ) return false;
}
int sum1 = code[1] + code[3] + code[5]
int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
int checksum_value = sum1 + sum2;
int checksum_digit = 10 - (checksum_value % 10);
if (checksum_digit == 10) checksum_digit = 0;
return checksum_digit;
}
Sorry for re-opening
JAVA VERSION
public int checkSum(String code){
int val=0;
for(int i=0;i<code.length();i++){
val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
}
int checksum_digit = 10 - (val % 10);
if (checksum_digit == 10) checksum_digit = 0;
return checksum_digit;
}
Reawakened with a C# version:
public static bool IsValidEan13(string eanBarcode)
{
return IsValidEan(eanBarcode, 13);
}
public static bool IsValidEan12(string eanBarcode)
{
return IsValidEan(eanBarcode, 12);
}
public static bool IsValidEan14(string eanBarcode)
{
return IsValidEan(eanBarcode, 14);
}
public static bool IsValidEan8(string eanBarcode)
{
return IsValidEan(eanBarcode, 8);
}
private static bool IsValidEan(string eanBarcode, int length)
{
if (eanBarcode.Length != length) return false;
var allDigits = eanBarcode.Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();
var s = length%2 == 0 ? 3 : 1;
var s2 = s == 3 ? 1 : 3;
return allDigits.Last() == (10 - (allDigits.Take(length-1).Select((c, ci) => c*(ci%2 == 0 ? s : s2)).Sum()%10))%10;
}
Here is a MySQL version for EAN13:
SET #first12digits="123456789012";
SELECT #first12digits,
IF (
(#check:=10-MOD(
(CAST(SUBSTRING(#first12digits, 1, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 2, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 3, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 4, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 5, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 6, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 7, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 8, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 9, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 10, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 11, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 12, 1) AS DECIMAL) * 3)
,10)) = 10, 0, #check
) AS checkDigit;
There was a bug. If Calc result = 10 then check digit = 0.
Here below a better version for EAN14.
SET #first13digits="1234567890123";
SELECT #txCode13:=#first13digits,
#iCheck := (
10 - (
(
MID(#txCode13, 2, 1) +
MID(#txCode13, 4, 1) +
MID(#txCode13, 6, 1) +
MID(#txCode13, 8, 1) +
MID(#txCode13, 10, 1) +
MID(#txCode13, 12, 1)
) + (
MID(#txCode13, 1, 1) +
MID(#txCode13, 3, 1) +
MID(#txCode13, 5, 1) +
MID(#txCode13, 7, 1) +
MID(#txCode13, 9, 1) +
MID(#txCode13, 11, 1) +
MID(#txCode13, 13, 1)
) * 3 ) % 10
) AS iCheck,
#iCheckDigit := IF(#iCheck = 10, 0, #iCheck) AS checkDigit,
CONCAT(#t
xCode13, CAST(#iCheckDigit AS CHAR)) AS EAN14WithCheck
Here is the Java version for EAN13
private int calcChecksum(String first12digits) {
char[] char12digits = first12digits.toCharArray();
int[] ean13 = {1,3};
int sum = 0;
for(int i = 0 ; i<char12digits.length; i++){
sum += Character.getNumericValue(char12digits[i]) * ean13[i%2];
}
int checksum = 10 - sum%10;
if(checksum == 10){
checksum = 0;
}
return checksum;
}
class GTIN(object):
def __init__(self, barcode=''):
self.barcode = barcode
def __checkDigit(self, digits):
total = sum(digits) + sum(map(lambda d: d*2, digits[-1::-2]))
return (10 - (total % 10)) % 10
def validateCheckDigit(self, barcode=''):
barcode = (barcode if barcode else self.barcode)
if len(barcode) in (8,12,13,14) and barcode.isdigit():
digits = map(int, barcode)
checkDigit = self.__checkDigit( digits[0:-1] )
return checkDigit == digits[-1]
return False
def addCheckDigit(self, barcode=''):
barcode = (barcode if barcode else self.barcode)
if len(barcode) in (7,11,12,13) and barcode.isdigit():
digits = map(int, barcode)
return barcode + str(self.__checkDigit(digits))
return ''
Today I need a PHP version, I remember about this page and copy from the Java version. Thank you.
function getEAN13($txEan12)
{
$iVal=0;
for($i=0; $i<strlen($txEan12); $i++)
{
$iSingleCharVal = intval(substr($txEan12, $i, 1)); // extract value of one char
$iSingleCharMult = $iSingleCharVal * ($i%2==0 ? 1 : 3); // calculate depending from position
$iVal+= $iSingleCharMult; // sum
}
$iCheckDigit = 10 - ($iVal % 10);
if ($iCheckDigit == 10) $iCheckDigit = 0;
return $txEan12 . $iCheckDigit;
}
Java Version:
It works perfectly
public static int checkSum(String code){
int val=0;
for(int i=0; i<code.length()-1; i++){
val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
}
int checksum_digit = (10 - (val % 10)) % 10;
return checksum_digit;
}
Python EAN13 check-digit calculation based on Najoua Mahi's Java function:
def generateEAN13CheckDigit(self, first12digits):
charList = [char for char in first12digits]
ean13 = [1,3]
total = 0
for order, char in enumerate(charList):
total += int(char) * ean13[order % 2]
checkDigit = 10 - total % 10
if (checkDigit == 10):
return 0
return checkDigit
This works on both EAN 13 and EAN8:
public static String generateEAN(String barcode) {
int first = 0;
int second = 0;
if(barcode.length() == 7 || barcode.length() == 12) {
for (int counter = 0; counter < barcode.length() - 1; counter++) {
first = (first + Integer.valueOf(barcode.substring(counter, counter + 1)));
counter++;
second = (second + Integer.valueOf(barcode.substring(counter, counter + 1)));
}
second = second * 3;
int total = second + first;
int roundedNum = Math.round((total + 9) / 10 * 10);
barcode = barcode + String.valueOf(roundedNum - total);
}
return barcode;
}
This is a code I wrote in VFP (Visual FoxPro 9), for both EAN-8 and EAN-13
Lparameters lcBarcode,llShowErrorMessage
If Vartype(m.lcBarcode)<>'C'
If m.llShowErrorMessage
MessageBox([Type of parameter is incorect!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If Len(Chrtran(Alltrim(m.lcBarcode),[0123456789],[]))>0
If m.llShowErrorMessage
MessageBox([Provided barcode contains invalid characters!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If Len(Alltrim(m.lcBarcode))=0
If m.llShowErrorMessage
MessageBox([The length of provided barcode is 0 (zero)!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If !InList(Len(Alltrim(m.lcBarcode)),8,13)
If m.llShowErrorMessage
MessageBox([Provided barcode is not an EAN-8 or EAN-13 barcode!],0+16,[Error Message])
EndIf
Return .f.
EndIf
Local lnCheck as Integer, lnSum as Integer, lnOriginalCheck as Integer,jj as Integer
jj=0
lnSum=0
m.lnOriginalCheck = Cast(Right(Alltrim(m.lcBarcode),1) as Integer)
m.lcBarcode = Left(Alltrim(m.lcBarcode),Len(Alltrim(m.lcBarcode))-1)
For ii = Len(m.lcBarcode) to 1 step -1
jj=jj+1
lnSum = lnSum + Cast(Substr(m.lcBarcode,ii,1) as Integer) * Iif(Mod(jj,2)=0,1,3)
Next
lnCheck = 10-Mod(lnSum,10)
lnCheck = Iif(lnCheck =10,0,lnCheck)
Return (lnCheck = lnOriginalCheck)
JavaScript version for EAN-8 and EAN-13
function checksum(code) {
const sum = code.split('').reverse().reduce((sum, char, idx) => {
let digit = Number.parseInt(char);
let weight = (idx + 1) % 2 === 0 ? 1 : 3;
let partial = digit * weight;
return sum + partial;
}, 0);
const remainder = sum % 10;
const checksum = remainder ? (10 - remainder) : 0;
return checksum;
}
Mini Javascript Version
function checksum(code){
return (10 - (code.split('').reduce((s, e, i) => { return s + parseInt(e) * ((i%2==0)?1:3) },0) % 10)) % 10;
}
=INT(CONCAT([#Code],MOD(10 - MOD((MID([#Code], 2, 1) + MID([#Code], 4, 1) + MID([#Code], 6, 1)) + (3*(MID([#Code], 1, 1) + MID([#Code], 3, 1) + MID([#Code], 5, 1) + MID([#Code], 7, 1))),10), 10)))
The above formula will calculate the check character without the need to use a macro or change to XLSM.
Note: Only works for EAN-8.

Resources