minimax.qbk 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. [section:minimax Minimax Approximations and the Remez Algorithm]
  2. The directory `libs/math/minimax` contains an interactive command-line driven
  3. program for the generation of minimax approximations using the Remez
  4. algorithm. Both polynomial and rational approximations are supported,
  5. although the latter are tricky to converge: it is not uncommon for
  6. convergence of rational forms to fail. No such limitations are present
  7. for polynomial approximations which should always converge smoothly.
  8. It's worth stressing that developing rational approximations to functions
  9. is often not an easy task, and one to which many books have been devoted.
  10. To use this tool, you will need to have a reasonable grasp of what the Remez
  11. algorithm is, and the general form of the approximation you want to achieve.
  12. Unless you already familar with the Remez method, you should first read the
  13. [link math_toolkit.remez brief background article explaining the principles behind the Remez algorithm].
  14. The program consists of two parts:
  15. [variablelist
  16. [[main.cpp][Contains the command line parser, and all the calls to the Remez code.]]
  17. [[f.cpp][Contains the function to approximate.]]
  18. ]
  19. Therefore to use this tool, you must modify f.cpp to return the function to
  20. approximate. The tools supports multiple function approximations within
  21. the same compiled program: each as a separate variant:
  22. NTL::RR f(const NTL::RR& x, int variant);
  23. Returns the value of the function /variant/ at point /x/. So if you
  24. wish you can just add the function to approximate as a new variant
  25. after the existing examples.
  26. In addition to those two files, the program needs to be linked to
  27. a [link math_toolkit.high_precision.use_ntl patched NTL library to compile].
  28. Note that the function /f/ must return the rational part of the
  29. approximation: for example if you are approximating a function
  30. /f(x)/ then it is quite common to use:
  31. [expression f(x) = g(x)(Y + R(x))]
  32. where /g(x)/ is the dominant part of /f(x)/, /Y/ is some constant, and
  33. /R(x)/ is the rational approximation part, usually optimised for a low
  34. absolute error compared to |Y|.
  35. In this case you would define /f/ to return [role serif-italic f(x)/g(x)] and then set the
  36. y-offset of the approximation to /Y/ (see command line options below).
  37. Many other forms are possible, but in all cases the objective is to
  38. split /f(x)/ into a dominant part that you can evaluate easily using
  39. standard math functions, and a smooth and slowly changing rational approximation
  40. part. Refer to your favourite textbook for more examples.
  41. Command line options for the program are as follows:
  42. [variablelist
  43. [[variant N][Sets the current function variant to N. This allows multiple functions
  44. that are to be approximated to be compiled into the same executable.
  45. Defaults to 0.]]
  46. [[range a b][Sets the domain for the approximation to the range \[a,b\], defaults
  47. to \[0,1\].]]
  48. [[relative][Sets the Remez code to optimise for relative error. This is the default
  49. at program startup. Note that relative error can only be used
  50. if f(x) has no roots over the range being optimised.]]
  51. [[absolute][Sets the Remez code to optimise for absolute error.]]
  52. [[pin \[true|false\]]["Pins" the code so that the rational approximation
  53. passes through the origin. Obviously only set this to
  54. /true/ if R(0) must be zero. This is typically used when
  55. trying to preserve a root at \[0,0\] while also optimising
  56. for relative error.]]
  57. [[order N D][Sets the order of the approximation to /N/ in the numerator and /D/
  58. in the denominator. If /D/ is zero then the result will be a polynomial
  59. approximation. There will be N+D+2 coefficients in total, the first
  60. coefficient of the numerator is zero if /pin/ was set to true, and the
  61. first coefficient of the denominator is always one.]]
  62. [[working-precision N][Sets the working precision of NTL::RR to /N/ binary digits. Defaults to 250.]]
  63. [[target-precision N][Sets the precision of printed output to /N/ binary digits:
  64. set to the same number of digits as the type that will be used to
  65. evaluate the approximation. Defaults to 53 (for double precision).]]
  66. [[skew val]["Skews" the initial interpolated control points towards one
  67. end or the other of the range. Positive values skew the
  68. initial control points towards the left hand side of the
  69. range, and negative values towards the right hand side.
  70. If an approximation won't converge (a common situation)
  71. try adjusting the skew parameter until the first step yields
  72. the smallest possible error. /val/ should be in the range
  73. \[-100,+100\], the default is zero.]]
  74. [[brake val][Sets a brake on each step so that the change in the
  75. control points is braked by /val%/. Defaults to 50,
  76. try a higher value if an approximation won't converge,
  77. or a lower value to get speedier convergence.]]
  78. [[x-offset val][Sets the x-offset to /val/: the approximation will
  79. be generated for `f(S * (x + X)) + Y` where /X/ is the
  80. x-offset, /S/ is the x-scale
  81. and /Y/ is the y-offset. Defaults to zero. To avoid
  82. rounding errors, take care to specify a value that can
  83. be exactly represented as a floating point number.]]
  84. [[x-scale val][Sets the x-scale to /val/: the approximation will
  85. be generated for `f(S * (x + X)) + Y` where /S/ is the
  86. x-scale, /X/ is the x-offset
  87. and /Y/ is the y-offset. Defaults to one. To avoid
  88. rounding errors, take care to specify a value that can
  89. be exactly represented as a floating point number.]]
  90. [[y-offset val][Sets the y-offset to /val/: the approximation will
  91. be generated for `f(S * (x + X)) + Y` where /X/
  92. is the x-offset, /S/ is the x-scale
  93. and /Y/ is the y-offset. Defaults to zero. To avoid
  94. rounding errors, take care to specify a value that can
  95. be exactly represented as a floating point number.]]
  96. [[y-offset auto][Sets the y-offset to the average value of f(x)
  97. evaluated at the two endpoints of the range plus the midpoint
  98. of the range. The calculated value is deliberately truncated
  99. to /float/ precision (and should be stored as a /float/
  100. in your code). The approximation will
  101. be generated for `f(x + X) + Y` where /X/ is the x-offset
  102. and /Y/ is the y-offset. Defaults to zero.]]
  103. [[graph N][Prints N evaluations of f(x) at evenly spaced points over the
  104. range being optimised. If unspecified then /N/ defaults
  105. to 3. Use to check that f(x) is indeed smooth over the range
  106. of interest.]]
  107. [[step N][Performs /N/ steps, or one step if /N/ is unspecified.
  108. After each step prints: the peek error at the extrema of
  109. the error function of the approximation,
  110. the theoretical error term solved for on the last step,
  111. and the maximum relative change in the location of the
  112. Chebyshev control points. The approximation is converged on the
  113. minimax solution when the two error terms are (approximately)
  114. equal, and the change in the control points has decreased to
  115. a suitably small value.]]
  116. [[test \[float|double|long\]][Tests the current approximation at float,
  117. double, or long double precision. Useful to check for rounding
  118. errors in evaluating the approximation at fixed precision.
  119. Tests are conducted at the extrema of the error function of the
  120. approximation, and at the zeros of the error function.]]
  121. [[test \[float|double|long\] N] [Tests the current approximation at float,
  122. double, or long double precision. Useful to check for rounding
  123. errors in evaluating the approximation at fixed precision.
  124. Tests are conducted at N evenly spaced points over the range
  125. of the approximation. If none of \[float|double|long\] are specified
  126. then tests using NTL::RR, this can be used to obtain the error
  127. function of the approximation.]]
  128. [[rescale a b][Takes the current Chebeshev control points, and rescales them
  129. over a new interval \[a,b\]. Sometimes this can be used to obtain
  130. starting control points for an approximation that can not otherwise be
  131. converged.]]
  132. [[rotate][Moves one term from the numerator to the denominator, but keeps the
  133. Chebyshev control points the same. Sometimes this can be used to obtain
  134. starting control points for an approximation that can not otherwise be
  135. converged.]]
  136. [[info][Prints out the current approximation: the location of the zeros of the
  137. error function, the location of the Chebyshev control points, the
  138. x and y offsets, and of course the coefficients of the polynomials.]]
  139. ]
  140. [endsect] [/section:minimax Minimax Approximations and the Remez Algorithm]
  141. [/
  142. Copyright 2006 John Maddock and Paul A. Bristow.
  143. Distributed under the Boost Software License, Version 1.0.
  144. (See accompanying file LICENSE_1_0.txt or copy at
  145. http://www.boost.org/LICENSE_1_0.txt).
  146. ]