function value = si ( x )

%*****************************************************************************80
%
%% si() computes the sine integral Si(x).
%
%  Licensing:
%
%    This routine is copyrighted by Shanjie Zhang and Jianming Jin.  However,
%    they give permission to incorporate this routine into a user program
%    provided that the copyright is acknowledged.
%
%  Modified:
%
%    09 August 2025
%
%  Author:
%
%    Original FORTRAN77 version by Shanjie Zhang, Jianming Jin.
%    This version by John Burkardt.
%
%  Reference:
%
%    Shanjie Zhang, Jianming Jin,
%    Computation of Special Functions,
%    Wiley, 1996,
%    ISBN: 0-471-11963-6,
%    LC: QA351.C45.
%
%  Input:
%
%    real x: the argument.
%
%  Output:
%
%    real value: the value of Si(x).
%
  p2 = 1.570796326794897;
  el = 0.5772156649015329;
  epsilon = 1.0E-15;
  x2 = x * x;
  xabs = abs ( x );
  if ( x < 0.0 )
    xsign = -1.0;
  else
    xsign = +1.0;
  end

  if ( xabs == 0.0 )

    value = 0.0;

  elseif ( xabs <= 16.0 )

    xr = xabs;
    value = xabs;
    for k = 1 : 40
      xr = - 0.5 * xr * ( 2 * k - 1 ) / k / ( 4 * k * k + 4 * k + 1 ) * x2;
      value = value + xr;
      if ( abs ( xr ) < abs ( value ) * epsilon )
        value = xsign * value
        return 
      end
    end

  elseif ( xabs <= 32.0 )

    m = floor ( 47.2 + 0.82 * xabs );
    bj = zeros ( m, 1 );
    xa1 = 0.0;
    xa0 = 1.0E-100;
    for k = m : -1 : 1
      xa = 4.0 * k * xa0 / xabs - xa1;
      bj(k) = xa;
      xa1 = xa0;
      xa0 = xa;
    end
    xs = bj(1);
    for k = 3 : 2 : m
      xs = xs + 2.0 * bj(k);
    end
    bj(1) = bj(1) / xs;
    for k = 2 : m
      bj(k) = bj(k) / xs;
    end
    xr = 1.0;
    xg1 = bj(1);
    for k = 2 : m
      xr = 0.25 * xr * ( 2.0 * k - 3.0 )^2 ...
        / ( ( k - 1.0 ) * ( 2.0 * k - 1.0 )^2 ) * xabs;
      xg1 = xg1 + bj(k) * xr;
    end

    xr = 1.0;
    xg2 = bj(1);
    for k = 2 : m
      xr = 0.25 * xr * ( 2.0 * k - 5.0 )^2 ...
        / ( ( k - 1.0 ) * ( 2.0 * k - 3.0 )^2 ) * xabs;
      xg2 = xg2 + bj(k) * xr;
    end

    xcs = cos ( xabs / 2.0 );
    xss = sin ( xabs / 2.0 );
    value = xsign * ( xabs * xcs * xg1 + 2.0 * xss * xg2 - sin ( xabs ) );

  else

    xr = 1.0;
    xf = 1.0;
    for k = 1 : 9
      xr = - 2.0 * xr * k * ( 2 * k - 1 ) / x2;
      xf = xf + xr;
    end
    xr = 1.0 / xabs;
    xg = xr;
    for k = 1 : 8
      xr = -2.0 * xr * ( 2 * k + 1 ) * k / x2;
      xg = xg + xr;
    end
    value = xsign * ( p2 - xf * cos ( xabs ) / xabs - xg * sin ( xabs ) / xabs );

  end

  return
end

