0

Let's say I have 3 functions, something like y_1(x) = x^2, y_2(x) = x+1 and y_3(x) = x/5. How do I apply these functions to any multidimensional float array in an element wise fashion?

Now given that I have the functions y_1, y_2 and y_3, what is a function that applies an arbitrary function to a float array of any size and shape?

I tried creating a function applier that takes in any function and then applying it to every element in a double loop for the 2 dimensional case but I cannot even get the function applier to take another function as input.

I tried doing the following

public float[][] elemen_wise_function(  float[][] x,
                                        int Size_axis_0,
                                        int Size_axis_1,
                                        Callable<> myFunc) {

    float[][] Constructed_array = new float[Size_axis_0][Size_axis_1];
    for (int i=0; i<Size_axis_0; i++) {
        for (int j = 0; j < Size_axis_1; j++) {
            Constructed_array[i][j] = (float) myFunc(x[i][j]) ;
        }
    }
    return Constructed_array;
}

But this fails because I cannot find a way to pass myFunc to elemen_wise_function.

9
  • 2
    map is the typical function to do this, although you'll need to use streams for that in Java. You could also just loop over the array using a standard for loop, and produce a new array using the loop. Commented Jan 15, 2019 at 20:44
  • do you want something like Arrays.map? possible duplicate of stackoverflow.com/a/3907448/10625458 Commented Jan 15, 2019 at 20:45
  • Show what you've tried. Commented Jan 15, 2019 at 20:45
  • And to take a function as an argument, look into the Function type. This question is a little broad though, as there's many ways to do what you're asking. Commented Jan 15, 2019 at 20:46
  • Do you know of any examples online? Commented Jan 15, 2019 at 20:46

3 Answers 3

2

One solution would be to declare myFunc as UnaryOperator<Float>.

public float[][] elemen_wise_function(float[][] x, int Size_axis_0, int Size_axis_1,
                                      UnaryOperator<Float> myFunc) {

Unfortunately that will autobox the float back and forth.

If performance is a concern you can define a custom interface that is hard-coded to operate on primitive floats:

interface FloatOperator {
    float apply(float x);
}

public float[][] elemen_wise_function(float[][] x, int Size_axis_0, int Size_axis_1,
                                      FloatOperator myFunc) {

In both cases use as:

    for (int i = 0; i < Size_axis_0; i++) {
        for (int j = 0; j < Size_axis_1; j++) {
            Constructed_array[i][j] = myFunc.apply(x[i][j]);
        }
    }

Invoke as (example):

    elemen_wise_function(array, size0, size1, a -> 1/a);
Sign up to request clarification or add additional context in comments.

Comments

0

Quite cool, you can pass a lambda (since java 8):

public float[][] elemen_wise_function(float[][] x,
                                      Function<Float, Float> f) {

    float[][] Constructed_array = new float[x.length][x[0].length];
    for (int i=0; i<x.length; i++) {
        for (int j = 0; j < x[0].length; j++) {
            Constructed_array[i][j] = f.apply(x[i][j]);
        }
    }
    return Constructed_array;
}

Then you can pass any function defined as lambda, for example:

Function<Float, Float> fun = x -> 2 * x;

Also one note - use camelCase in java for method names;)

7 Comments

Using Function<Float, Float> has a disadvantage of forcing auto-boxing to Float objects (and back to float) which is extra overhead.
That is true. It can be visible in costly operations.
I like that you took 2 inputs out of my function! Thanks.
Yeah, those were redundant, as they could be easily derived:)
As a followup question, how would I specify a function with multiple inputs? So to replace Function<Float, Float>, what would be correct syntax to indicate Function<Float, [Float, Float]>?
|
0

If you are trying to do this with Java 6, you can do something like.

    import java.util.Arrays;
    import java.util.function.Function;

    public interface MapFunction {
        public float map(float value);
    }

    public static float[][] map2DArray(float[][] floatArrays, MapFunction mapper) {
        final float[][] retval = new float[floatArrays.length][];
        for (int i = 0; i < floatArrays.length; i++) {
            float [] floats = floatArrays[i];
            retval[i] = new float[floats.length];
            for (int j = 0; j < floats.length; j++) {
                retval[i][j] = mapper.map(floats[j]);
            }
        }
        return retval;
    }

Or in Java 8 and you don't mind using Float

    import java.util.Arrays;
    import java.util.function.Function;

    public static Float[][] map2DArray(Float[][] floatArrays, Function<Float, Float> mapper) {
        return Arrays.stream(floatArrays).map((Float[] floats) -> 
                Arrays.stream(floats).map(mapper).toArray(Float[]::new)
        ).toArray(Float[][]::new);
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.