4

I want to validate all the elemnent of an array. If an element is under a value, swap by a min value and if it is above a value, swap by a max value.

But I don´t know how I can do it optimized. For do it I go above all elements, element by element but it is not optimized, and it spend a lot of cpu time in very large arrays.

This is an example of my code:

#include <iostream> 
#include <math.h>
const int MAX = 10;
int main ()
{
    float minVal = 2.0;
    float maxVal = 11.0;

    float vElem[] = {-111111.0/0.0, 10.0, 90.0, 8.0, -7.0,
                    -0.6, 5.0, 4.0, 33.0, 222222222.0/0};

    for(int i=0; i<MAX; i++){
            if(isinf(vElem[i])==-1 || vElem[i]<minVal) vElem[i] = minVal;
            if(isinf(vElem[i])==1 || vElem[i]>maxVal || isnan(vElem[i])) vElem[i] = maxVal;

            std::cout << vElem[i]<< std::endl;
    }
}
user3480234
  • 65
  • 1
  • 5
  • 1
    I don't see any other options... you must check each one of the elements and decide what to do according to your logic. even if there is a fancy C++ construct, it will underline do the same (iterate over all elements and perform the check operations on it) – NirMH May 27 '14 at 08:09
  • You can use Auto-Parallelization using OpenMP or something if you have multiple cores. Include the header and put `#pragma omp parallel for` above the loop – Montaldo May 27 '14 at 08:13
  • What version of C++ do you have access to ? (ie, is C++11 okay ?) – Matthieu M. May 27 '14 at 08:17
  • 1
    Is I/O actually necessary to your use case ? Because I/O overhead trumps *everything* you are doing in your loop. – Matthieu M. May 27 '14 at 08:46
  • I have g++ version 4.1.2. The initial input is not necessary – user3480234 May 27 '14 at 10:15
  • 1
    Possible duplicate of [Most efficient/elegant way to clip a number?](https://stackoverflow.com/questions/9323903/most-efficient-elegant-way-to-clip-a-number) – phuclv Aug 22 '18 at 05:30

2 Answers2

5

I don't think using elaborate constructs would buy you much here. Maybe making your code a bit cleaner ?

std::for_each(std::begin(vElem), std::end(vElem), [](float &val) {
    val = clamp(val, minVal, maxVal);
});

this is what a typicall clamp function returns

Community
  • 1
  • 1
Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • 1
    You say that “elaborate constructs would [not] buy you much” and yet your code is *vastly* cleaner than OP’s (although `std::transform` would be more appropriate than `std::for_each`). – Konrad Rudolph May 27 '14 at 09:08
  • @KonradRudolph Yes, I was reffering to usage of filtered boost ranges etc. didn't use `transform` to avoid specifying a `result` iterator; I agree it would communicate intentions clearly – Nikos Athanasiou May 27 '14 at 09:15
  • The `result` iterator is just `std::begin(vElem)`: `std::transform` can work in-place. – Konrad Rudolph May 27 '14 at 09:16
  • Its a good idea, if it couldn`t be optimize. I have g++ version 4.1.2, so I couldn`t use it, but I have rewrite it using your adviced. I have used for_each and although I haven`t installed this package of boost in my project, I have used std::min( std::max( val, minVal ), maxVal ) and is more clearly – user3480234 May 27 '14 at 09:34
  • @user3480234 Update your GCC, it’s *woefully* outdated. – Konrad Rudolph May 27 '14 at 09:58
  • @KonradRudolph Yes, obviously, I meant literally, didn't want to write `std::begin(vElem)` once more; QuickQ : Would you recommend any specific tools in **your** range library that would help for more elegant code in this specific case? – Nikos Athanasiou May 27 '14 at 10:04
0
  for(int i=0; i<MAX; i++){
      float c = vElem[i];

      //Could convert c to an integer here, so the below uses integer operations
      //Additional cost is two multiplications (scaling up and scaling back down).

      float n = c + ((c < min) * (min - c)) + ((c > max) * (max - c));
      std::cout << n << std::endl;
  }
  • Two multiplications
  • Four additions
  • Two comparisons

I think this is faster than any of the clamp() implementations referred to in the other answer.

user997112
  • 29,025
  • 43
  • 182
  • 361
  • The floating point operations (the four additions, the two multiplications, and even the two comparisons) are costly, compared to operations on integral types. The `clamp()` function is only two comparisons, conditional jumps. My guess is that the `clamp()` function is faster. Anyway, one cannot know without a bench. – lrineau May 28 '14 at 11:45
  • The linked-to answer is: return n <= lower ? lower : n >= upper ? upper : n; which is ternary operator, which means conditional branches. If you never had to branch- might be faster, but if you did the performance cost would be significant. – user997112 May 28 '14 at 12:18
  • and you could convert the floats to integers at the beginning, use integer arithmetic and then scale the integer back to a float. – user997112 May 28 '14 at 12:19