File : mapping.sp


$ spar mapping.sp
 0.0 maps to: -1.00000000000000E+00
-1.00000000000000E+00 maps back to:  0.00000000000000E+00
 1.00000000000000E+00 maps to: -9.00000000000000E-01
-9.00000000000000E-01 maps back to:  1.00000000000000E+00
 2.00000000000000E+00 maps to: -8.00000000000000E-01
-8.00000000000000E-01 maps back to:  2.00000000000000E+00
 3.00000000000000E+00 maps to: -7.00000000000000E-01
-7.00000000000000E-01 maps back to:  3.00000000000000E+00
 4.00000000000000E+00 maps to: -6.00000000000000E-01
-6.00000000000000E-01 maps back to:  4.00000000000000E+00
 5.00000000000000E+00 maps to: -5.00000000000000E-01
-5.00000000000000E-01 maps back to:  5.00000000000000E+00
 6.00000000000000E+00 maps to: -4.00000000000000E-01
-4.00000000000000E-01 maps back to:  6.00000000000000E+00
 7.00000000000000E+00 maps to: -3.00000000000000E-01
-3.00000000000000E-01 maps back to:  7.00000000000000E+00
 8.00000000000000E+00 maps to: -2.00000000000000E-01
-2.00000000000000E-01 maps back to:  8.00000000000000E+00
 9.00000000000000E+00 maps to: -1.00000000000000E-01
-1.00000000000000E-01 maps back to:  9.00000000000000E+00
 1.00000000000000E+01 maps to:  0.00000000000000E+00
 0.00000000000000E+00 maps back to:  1.00000000000000E+01

#!/usr/local/bin/spar

pragma annotate( summary, "mapping" )
       @( description, "The task is to write a function/subroutine/... that takes" )
       @( description, "two ranges and a real number, and returns the mapping of" )
       @( description, "the real number from the first to the second range. Use" )
       @( description, "this function to map values from the range [0, 10] to the" )
       @( description, "range [-1, 0]." )
       @( see_also, "http://rosettacode.org/wiki/Map_range" )
       @( author, "Ken O. Burtch" );
pragma license( unrestricted );

pragma restriction( no_external_commands );

procedure mapping is
   type first_range  is new float;
   type second_range is new float;
   -- Spar doesn't implement ranges so we'll use constants
   first_range_first : constant first_range := 0.0;
   first_range_last : constant first_range := 10.0;
   second_range_first : constant second_range := -1.0;
   second_range_last : constant second_range := 0.0;

   function translate (first_range_value : first_range) return second_range is
      b1 : constant float := float( second_range_first );
      b2 : constant float := float( second_range_last );
      a1 : constant float := float( first_range_first );
      a2 : constant float := float( first_range_last );
      result : float;
   begin
      result := b1 + (float (first_range_value) - a1) * (b2 - b1) / (a2 - a1);
      return second_range(result);
   end translate;

   function translate_back (second_range_value : second_range) return first_range is
      b1 : constant float := float (first_range_first);
      b2 : constant float := float (first_range_last);
      a1 : constant float := float (second_range_first);
      a2 : constant float := float (second_range_last);
      result : float;
   begin
      result := b1 + (float (second_range_value) - a1) * (b2 - b1) / (a2 - a1);
      return first_range (result);
   end translate_back;

   test_value            : first_range := first_range_first;
   translated_value      : second_range;
   translated_back_value : first_range;
begin
   loop
      translated_value := translate( test_value );
      translated_back_value := translate_back( translated_value );

      ? strings.image(test_value) & " maps to: "
                          & strings.image (translated_value);
      ? strings.image(translated_value) & " maps back to: "
                          & strings.image (translated_back_value);
      exit when test_value = first_range_last;
      test_value := @ + 1.0;
   end loop;
end mapping;

-- VIM editor formatting instructions
-- vim: ft=spar