Proposal for 'math.e' (2007-08-07)

new topic     » topic index » view thread      » older message » newer message

This is my current (2007-08-07) proposal for a "math.e" standard
include file, according to the recent discussion here on EUforum.

Changes compared to the previous version:
- Now the global constants have maximum available precision ( hopefully smile ).
  Note:
  E.g.   EULER_NORMAL = 1/sqrt(TWO_PI)    has the same precision as
         EULER_NORMAL = machine_func(47, {81,54,212,51,69,136,217,63})
- Aded two new global constants.
- Added internal constants RADIANS_TO_DEGREES and DEGREES_TO_RADIANS.
- Added a general logarithm function.
- Added functions polar_to_rect() and rect_to_polar().
- Renamed 4 functions, according to this post by Fernando Bauer
<http://www.openeuphoria.org/cgi-bin/esearch.exu?fromMonth=8&fromYear=C&toMonth=8&toYear=C&postedBy=Fernando+Bauer&keywords=Aug+3>
  and to the discussion which it triggered.
  - find_least()    ->  find_min()
  - find_greatest() ->  find_max()
  - least()         ->  min()
  - greatest()      ->  max()

global constant
   E            = 2.7182818284590452,
   PI           = 3.1415926535897932,
EULER_GAMMA  = 0.57721566490153286,  -- the Euler-Mascheroni-Soldner gamma
   constant
   LN2          = log(2),
   LN10         = log(10),
   SQRT2        = sqrt(2),
   HALF_SQRT2   = SQRT2/2.0,
   HALF_PI      = PI/2.0, 
   QUARTER_PI   = PI/4.0, 
   TWO_PI       = PI*2.0, 
   EULER_NORMAL = 1/sqrt(TWO_PI) 


global function log2 (object x)
   -- logarithm base 2
   -- in : (sequence of) real number(s) > 0
   -- out: (sequence of) real number(s)
   -- Note: This function returns _exact_ results for all integral
   --       powers of 2 in the half-closed interval ]0,#FFFFFFFF]

   if atom(x) then
      if x = #20000000 then
         return 29               -- log(x)/LN2 is imprecise in this case 
      elsif x = #80000000 then
         return 31               -- log(x)/LN2 is imprecise in this case
      else 
         return log(x)/LN2
      end if
   end if

   for i = 1 to length(x) do
      x[i] = log2(x[i])
   end for
   return x
end function

global function log10 (object x)
   -- logarithm base 10
   -- in : (sequence of) real number(s) > 0
   -- out: (sequence of) real number(s)

   return log(x)/LN10
end function

type positive_not_1 (object x)
   if atom(x) and x > 0 then
      return x != 1
   end if
   return 0
end type

global function logx (object x, positive_not_1 base)
   -- general logarithm function
   -- in  : x   : (sequence of) atom(s) > 0
   --       base: atom > 0 and != 1
   -- out : (sequence of) atom(s)
   -- Note: If x = 1 then the function returns 0 for any possible base.

   return log(x)/log(base)
end function

global function exp (object x)
   return power(E, x)
end function

global function sinh (object x)
   return (exp(x) - exp(-x)) / 2
end function

global function cosh (object x)
   return (exp(x) + exp(-x)) / 2
end function

global function tanh (object x)
   return sinh(x) / cosh(x)
end function

global function arcsinh (object x)
   return log(x + sqrt(x*x+1))
end function

type not_below_1 (object x)
   if atom(x) then
      return x >= 1.0
   end if

   for i = 1 to length(x) do
      if not not_below_1(x[i]) then
         return 0
      end if
   end for
   return 1
end type

global function arccosh (not_below_1 x)
   return log(x + sqrt(x*x-1))
end function

type abs_below_1 (object x)
   if atom(x) then
      return x > -1.0 and x < 1.0
   end if

   for i = 1 to length(x) do
      if not abs_below_1(x[i]) then
         return 0
      end if
   end for
   return 1
end type

global function arctanh (abs_below_1 x)
   return log((1+x)/(1-x)) / 2
end function

global function abs (object x)
   -- return the absolute value of (all elements of) x

   if atom(x) then
      if x < 0 then
         return -x
      else
         return x
      end if
   end if

   for i = 1 to length(x) do
      x[i] = abs(x[i])
   end for
   return x
end function

global function sign (object x)
   --  x < 0  ==>  -1
   --  x = 0  ==>   0
   --  x > 0  ==>  +1

   if atom(x) then
      return compare(x, 0)
   end if

   for i = 1 to length(x) do
      x[i] = sign(x[i])
   end for
   return x
end function

global function ceil (object x)
   -- the opposite of floor()
   -- Examples: ? ceil(3.2)          --> 4
   --           ? ceil({-3.2,7,1.6}) --> {-3,7,2}

   return -floor(-x)
end function

global function sum (sequence list)
   -- Return the sum of all elements in 'list'.
   -- Note: This does not do a recursive sum of sub-sequences.
   atom ret

   ret = 0
   for i = 1 to length(list) do
      ret += list[i]
   end for
   return ret
end function

constant RADIANS_TO_DEGREES = 180.0/PI

global function radians_to_degrees (object x)
   -- in : (sequence of) angle(s) in radians
   -- out: (sequence of) angle(s) in degrees

   return x * RADIANS_TO_DEGREES
end function

constant DEGREES_TO_RADIANS = PI/180.0

global function degrees_to_radians (object x)
   -- in : (sequence of) angle(s) in degrees
   -- out: (sequence of) angle(s) in radians

   return x * DEGREES_TO_RADIANS
end function

type trig_range (object x)
   --  values passed to arccos and arcsin must be [-1,+1]
   if atom(x) then
      return x >= -1 and x <= 1
   end if

   for i = 1 to length(x) do
      if not trig_range(x[i]) then
         return 0
      end if
   end for
   return 1
end type

global function arcsin (trig_range x)
   -- returns angle in radians
   return 2 * arctan(x / (1.0 + sqrt(1.0 - x * x)))
end function

global function arccos (trig_range x)
   -- returns angle in radians
   return HALF_PI - 2 * arctan(x / (1.0 + sqrt(1.0 - x * x)))
end function

type point_pol (object x)
   if sequence(x) and (length(x) = 2)
   and atom(x[1]) and (x[1] >= 0)
   and atom(x[2]) then
      return 1 
   end if
   return 0
end type

global function polar_to_rect (point_pol p)
   -- convert polar coordinates to rectangular coordinates
   -- in : sequence of two atoms: {distance, angle};
   --      'distance' must be >= 0, 'angle' is in radians 
   -- out: sequence of two atoms: {x, y}
   atom distance, angle, x, y

   distance = p[1]
   angle = p[2]
   x = distance*cos(angle)
   y = distance*sin(angle)
   return {x, y}
end function

type point_xy (object x)
   if sequence(x) and (length(x) = 2)
   and atom(x[1])
   and atom(x[2]) then
      return 1 
   end if
   return 0
end type

global function rect_to_polar (point_xy p)
   -- convert rectangular coordinates to polar coordinates
   -- in : sequence of two atoms: {x, y}
   -- out: sequence of two elements: {distance, angle}
   --      - 'distance' is always an atom >= 0
   --      - 'angle' is normally an atom that expresses radians,
   --        and is in the half-closed interval ]-PI,+PI].
   --        If 'distance' equals 0, then 'angle' is {},
   --        meaning that it is undefined in this case.
   object angle
   atom distance, x, y

   x = p[1]
   y = p[2]
   distance = sqrt(x*x + y*y)
   if x > 0 then
      angle = arctan(y/x) 
   elsif x < 0 then
      if y < 0 then
         angle = arctan(y/x) - PI
      else
         angle = arctan(y/x) + PI
      end if
   else
      if y < 0 then
         angle = -HALF_PI
      elsif y > 0 then
         angle = HALF_PI
      else
         angle = {}            -- The angle is undefined in this case.
      end if
   end if
   return {distance, angle}
end function

global function find_min (sequence list, integer start)
   -- Search for the minimum value in 'list', beginning at index 'start'.
   -- Return the index of that element.
   -- Notes: This does not do a recursive compare on sub-sequences.
   --        An empty sequence will cause a runtime error.
   object temp
   integer ret

   temp = list[start]
   ret = start
   for i = start+1 to length(list) do
      if compare(temp, list[i]) = 1 then
         temp = list[i]
         ret = i
      end if
   end for
   return ret
end function

global function find_max (sequence list, integer start)
   -- Search for the maximum value in 'list', beginning at index 'start'.
   -- Return the index of that element.
   -- Notes: This does not do a recursive compare on sub-sequences.
   --        An empty sequence will cause a runtime error.
   object temp
   integer ret

   temp = list[start]
   ret = start
   for i = start+1 to length(list) do
      if compare(temp, list[i]) = -1 then
         temp = list[i]
         ret = i
      end if
   end for
   return ret
end function

global function min (sequence list, integer start)
   -- Search for the minimum value in 'list', beginning at index 'start'.
   -- Return the value of that element.
   -- Notes: This does not do a recursive compare on sub-sequences.
   --        An empty sequence will cause a runtime error.
   object ret

   ret = list[start]
   for i = start+1 to length(list) do
      if compare(ret, list[i]) = 1 then
         ret = list[i]
      end if
   end for
   return ret
end function

global function max (sequence list, integer start)
   -- Search for the maximum value in 'list', beginning at index 'start'.
   -- Return the value of that element.
   -- Notes: This does not do a recursive compare on sub-sequences.
   --        An empty sequence will cause a runtime error.
   object ret

   ret = list[start]
   for i = start+1 to length(list) do
      if compare(ret, list[i]) = -1 then
         ret = list[i]
      end if
   end for
   return ret
end function

global function lesser (object x1, object x2)
   -- Return the argument with the lesser value.
   -- Note: This does not do a recursive compare on sub-sequences.

   if compare(x1, x2) <= 0 then
      return x1
   else
      return x2
   end if
end function

global function greater (object x1, object x2)
   -- Return the argument with the greater value.
   -- Note: This does not do a recursive compare on sub-sequences.

   if compare(x1, x2) >= 0 then
      return x1
   else
      return x2
   end if
end function

Regards,
   Juergen

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu