title: Fast round up/down double in fortran?
body: <p>Is there fast way to do round up/down in Fortran? </p>
  
  <p>Because of linear order of bit-representation of positive double numbers it's possible to implement rounding as below. </p>
  
  <p><code>pinf</code> and <code>ninf</code> are global constants which are +/- infinity respectively </p>
  
  <pre><code>function roundup(x)
      double precision ,intent(in) :: x
      double precision :: roundup
  
      if (isnan(x))then 
          roundup = pinf
          return
      end if 
      if (x==pinf)then
          roundup = pinf
          return 
      end if
      if (x==ninf)then
          roundup = ninf
          return 
      end if
      if (x&gt;0)then
          roundup = transfer((transfer(x,1_8)+1_8),1d0)
      else if (x&lt;0) then
          roundup = transfer((transfer(x,1_8)-1_8),1d0)
      else
          if (transfer(x,1_8)==Z'0000000000000000')then
              roundup = transfer((transfer(x,1_8)+1_8),1d0)
          else
              roundup = transfer((transfer(-x,1_8)+1_8),1d0)
          end if 
      end if 
  end function roundup
  </code></pre>
  
  <p>I feel it's not the best way to do that because it's slow, but it uses almost only bit-operations.</p>
  
  <p>Another way is using multiplication and some epsilon 
  <code>eps = epsilon (1d0)</code> </p>
  
  <pre><code>function roundup2(x)
      double precision ,intent(in) :: x
      double precision :: roundup2
      if (isnan(x)) then 
          roundup2 = pinf
          return 
      else if (x&gt;=eps) then 
          roundup2 = x*(1d0+eps)
      else if (x&lt;=-eps) then 
          roundup2 = x*(1d0-eps)
      else 
          roundup2 = eps
      end if 
  end function roundup2
  </code></pre>
  
  <p>For some <code>x</code> both functions returns the same result (1d0, 158d0), for some don't (0.1d0, 15d0). </p>
  
  <p>The first function is more accurate, but it's about 3.6 times slower than second 
  (11.1 vs 3.0 seconds on 10^9 rounds test)</p>
  
  <pre><code>    print * ,x,y,abs(x-y)
      do i = 1, 1000000000
          x = roundup(x)
          !y = roundup2(y)
      end do 
      print * ,x,y,abs(x-y)
  </code></pre>
  
  <p>With no checks for NaN/Infinities first function test takes 8.5 seconds (-20%). </p>
  
  <p>I use round function really hard and it takes a lot of time in profile of program. Is there cross-platform way to round faster with no loose of precision? </p>
  
  <p><strong>Update</strong></p>
  
  <p>The question suspects calls of roundup and rounddown at the time with no ability to reorder them. I didn't mention rounddown to keep topic short. </p>
  
  <p>Hint:
  First function uses two <code>transfer</code> function and one adding. And it's slower than one multiplication and one adding in the second case. Why transfer cost so much when it doesn't do any with the number's bits? Is it possible to replace transfer by faster function(s) or avoid addition calls at all?</p>