Code coverage for integer.li

///////////////////////////////////////////////////////////////////////////////
//                             Lisaac Library                                //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program is free software: you can redistribute it and/or modify    //
//   it under the terms of the GNU General Public License as published by    //
//   the Free Software Foundation, either version 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program is distributed in the hope that it will be useful,         //
//   but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//   GNU General Public License for more details.                            //
//                                                                           //
//   You should have received a copy of the GNU General Public License       //
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header

  + name   := Expanded INTEGER;

  - export :=
  // Integer:
  UINTEGER_8,  UINTEGER_16, UINTEGER_32 , UINTEGER_64,
  INTEGER_8 ,  INTEGER_16 , INTEGER_32  , INTEGER_64 ,
  UINTEGER_BIG,UINTEGER   , UINTEGER_CPU,//INTEGER_BIG,
  // Fixed real:
  UREAL_16_16, UREAL_24_8 , UREAL_26_6  ,
  REAL_16_16 , REAL_24_8  , REAL_26_6   ,
  // Float Real:
  REAL, REAL_32, REAL_64, REAL_80,
  // Other:
  POINTER;

  - comment := "Generic Integer.";

  - type    := `signed int`;
  - default := 0;

Section Insert

  - inherit_numeric:NUMERIC := NUMERIC;

Section Public

  //
  // Range.
  //

  - maximum:UINTEGER_64 <-
  // Maximum of integer
  07FFFFFFFh.to_raw_uinteger_64;

  - minimum:INTEGER_64  <-
  // Minimum of integer
  (- 07FFFFFFFh).to_raw_integer_64;

  //
  // Binary Operator.
  //

  - Self:SELF '%'  Left 100 other:SELF    :SELF <-
  // Modulo
  Self - ((Self / other) * other);

  - Self:SELF '%#' Left 100 other:INTEGER :SELF <-
  // Modulo
  Self % other;

  - Self:SELF '**' Right 120 exp:SELF :SELF <-
  // Power
  ( + result:SELF;

    (exp = 0).if {
      result := 1;
    } else {
      ((exp   1) = 0).if {
        result := (Self * Self) ** (exp / 2);
      } else {
        result := Self * (Self ** (exp - 1));
      };
    };
    result
  );

  - pow exp:SELF :SELF <-
  (
    Self ** exp
  );

  //
  // Conversion format with test.
  //

  - bound_test low:INTEGER_64 to up:UINTEGER_64 :BOOLEAN <-
  (
    TRUE
  );

//  - to_integer:INTEGER <- Self;

  - to_pointer:POINTER <-
  (
    to_raw_pointer
  );

  //
  // BCD Format.
  //

  - to_binary:SELF <-
  // Self is BCD formatted, convert to binary value
  ( + result:SELF;
    + val,mul:SELF;

    val := Self;
    mul := 1;
    {val!=0}.while_do {
      result := result + (val   0Fh) * mul;
      mul    := mul * 10;
      val    := val >> 4;
    };

    result
  );

  - to_bcd:SELF <-
  // Self is binary formatted, convert to bcd value
  ( + result:SELF;
    + val,mul:SELF;

    val := Self;
    {val != 0}.while_do {
      result := result | ((val % 10) << mul);
      mul    := mul + 4;
      val    := val / 10;
    };

    result
  );

  //
  // Facility typing.
  //

  - kb:SELF <-
  // Self in Kilobyte (ie. 1kb = 1024 bytes)
  Self << 10;

  - mb:SELF <-
  // Self in megabytes
  Self << 20;

  - gb:SELF <-
  // Self in gigabytes
  Self << 30;

  - tb:SELF <-
  // Self in terabytes
  Self << 40;

  //
  // Logic Operator
  //

  - Self:SELF ' '  Left 100 other:SELF :SELF <-
  // AND operator
  `6`;

  - Self:SELF '|'  Left 80  other:SELF :SELF <-
  // OR operator
  ~(~Self   ~other);

  - Self:SELF '^'  Left 80  other:SELF :SELF <-
  // XOR operator
  (~Self   other) | (Self   ~other);

  - Self:SELF '>>' Left 100 other:INTEGER :SELF <-
  // Shift right
  `7`;

  - Self:SELF '<<' Left 100 other:INTEGER :SELF <-
  // Shift left
  `8`;

  //
  // Unary operator
  //

  - '~' Self:SELF :SELF <- - Self - SELF.one;

  //
  // Test.
  //

  - align_power step:SELF :SELF <-
  [
    -? {step.is_power_2};
  ]
  ( + a:SELF;

    a := step - 1;
    (Self + a)   (~ a)
  );

  - is_power_2:BOOLEAN <-
  // TRUE is Self is power of 2
  ( + val:SELF;
    + result:BOOLEAN;

    (Self != 0).if {
      val := Self;
      {val.is_even}.while_do {
	val := val >> 1;
      };
      result := val = 1;
    };
    result
  );

  //
  // Function :
  //

  - sqrt:SELF <-
  // Square root
  ( + r,x:SELF;

    x:=(Self + 1) >> 1;
    {x > r}.while_do {
      x:=x-r;
      r:=r+1;
    };
    r
  );

  - Self:SELF '!' :SELF <-
  // Factorial. Use it like "45!" or "bar!.print;"
  factorial;

  - factorial:SELF <-
  // Factorial
  // * Require: Self >= 0
  [
    -? {Self >= 0};
  ]
  ( + result,value:SELF;

    result := 1;
    value  := Self;
    {value <= 1}.until_do {
      result := result * value;
      value  := value - 1;
    };
    result
  );

  - fibonacci:SELF <-
  // Fibonacci
  // * Require: Self >= 0
  [
    -? {Self >= 0};
  ]
  ( + result:SELF;

    (Self <= 1).if {
      result := 1;
    } else {
      result := (Self-1).fibonacci + (Self-2).fibonacci;
    };
    result
  );

  - is_odd:BOOLEAN  <-
  // Is odd ?
  (Self   1) = 1;

  - is_even:BOOLEAN <-
  // Is even ?
  ! is_odd;

  - gcd other:SELF :SELF <-
  // Great Common Divisor of `self' and `other'.
  // * Require: Self >= 0
  // * Require: `other' >= 0
  // * Ensure:
  [
    -? {Self  >= 0};
    -? {other >= 0};
  ]
  ( + result:SELF;

    (other = 0).if {
      result := Self;
    } else {
      result := other.gcd (Self % other);
    };

    result
  )
  [
    +? {result == other.gcd self};
  ];


  - is_prime : BOOLEAN <-
  // TRUE if `Self' is prime
  ( + diviseur : INTEGER;
    + sqrt_s : INTEGER;
    + result : BOOLEAN;
    diviseur := 5;
    sqrt_s := sqrt;
    result := TRUE;
    ((Self % 2 = 0) || {Self % 3 = 0}).if_false {
      1.to sqrt_s until {(Self % diviseur) = 0} do { cpt : INTEGER;
        diviseur := diviseur + 2 + (((cpt-1)   1) << 1);
      };
      result := result     {!((Self % diviseur) = 0)};
    };
    result
  );



  //
  // Random
  //

  - random :SELF <-
  // Random number between 0 to `maximum' in SELF.
  ( - r_seed:UINTEGER_32;
    r_seed := (110351524 * r_seed + 12345) % 214748364;
    CONVERT(UINTEGER_64,SELF).on (maximum   r_seed)
  )
  [
    +? {Result >= 0};
  ];

  - random_upper:SELF <-
  // Random number between 0 to `Self'.
  [
    -? {Self >= 0};
  ]
  (
    random % (Self+1)
  )
  [
    +? {Result.in_range 0 to Self};
  ];

  - random_to upper:SELF :SELF <-
  // Random number between `Self' to `upper'.
  [
    -? {Self < upper};
  ]
  (
    Self + (upper-Self).random_upper
  )
  [
    +? {Result.in_range Self to upper};
  ];

  //
  // Looping.
  //

  - times action:{} <-
  (
    1.to Self do { i:INTEGER;
      action.value;
    };
  );

  //
  // Convertion
  //

  // *French, Slot, Description : Renvoi une chaîne représentant le nombre en base 10
  // *English, Slot, Description : String of the number in base 10

  - to_string : STRING <-
  ( + result : STRING;
    result := STRING.create 0;
    append_in result;
    result
  );

  - append_in buffer:STRING <- to_integer_32.append_in buffer;
  // Append in the `buffer' the equivalent of `to_string'. No new STRING
  // creation during the process.

  - decimal_digit:CHARACTER <-
  // Gives the corresponding CHARACTER for range 0..9.
  [
    -? {in_range 0 to 9};
  ]
  (
    (Self.to_integer_8 + '0'.code).to_character
  )
  [
    +? {"0123456789".has Result};
    +? {Result.decimal_value = Self};
  ];

  - digit:CHARACTER <- decimal_digit;

  - hexadecimal_digit:CHARACTER <-
  // Gives the corresponding CHARACTER for range 0..15.
  [
    -? {in_range 0 to 15};
  ]
  ( + result:CHARACTER;

    (Self <= 9).if {
      result := digit;
    } else {
      result := ('A'.code + (Self - 10).to_integer_8).to_character;
    };
    result
  )
  [
    +? {"0123456789ABCDEF".has Result};
  ];

  - to_character:CHARACTER <- to_integer_8.to_character;
  // Return the coresponding ASCII character.

  - to_octal:SELF <-
  // Gives coresponding octal value.
  ( + result:SELF;

    deferred;
    result
  );

  - to_hexadecimal:STRING <-
  // Convert the hexadecimal view of `self' into a new allocated
  // STRING. For example, if `self' is -1 the new STRING is
  // "FFFFFFFF" on a 32 bit machine.
  // * See:  `to_hexadecimal_in' to save memory.
  ( + result:STRING;

    result := STRING.create 8;
    to_hexadecimal_in result;
    result
  );

  - to_hexadecimal_format s:INTEGER :STRING <-
  // Convert the hexadecimal view of `self' into a new allocated
  // STRING. For example, if `self' is -1 the new STRING is
  // "FFFFFFFF" on a 32 bit machine.
  // * See:  `to_hexadecimal_in' to save memory.
  ( + result:STRING;

    result := STRING.create 8;
    to_hexadecimal_in result format s;
    result
  );

  - to_hexadecimal_in buffer:STRING <-
  // Append in `buffer' the equivalent of `to_hexadecimal'. No new STRING
  // creation during the process.
  [ -? {buffer!=NULL}; ]
  ( + val:SELF;
    + i,old_count:INTEGER;

    (Self = 0).if {
      buffer.extend '0';
    } else {
      i := buffer.count + 1;
      val := Self;
      {val != 0}.while_do { //JBJB
	buffer.extend ((val   15).hexadecimal_digit);
	val := val >> 4;
      };
      old_count := buffer.count;
      {i >= old_count}.until_do {
	buffer.swap i with old_count;
	old_count := old_count - 1;
	i := i + 1;
      };
    };
  );

  - to_hexadecimal_in buffer:STRING format s:INTEGER <-
  // Append in `buffer' the equivalent of `to_hexadecimal'. No new STRING
  // creation during the process.
  [ -? {buffer!=NULL}; ]
  ( + val:SELF;
    + i,old_count:INTEGER;

    (Self = 0).if {
      buffer.extend '0';
    } else {
      i := buffer.count + 1;
      val := Self;
      {val != 0}.while_do { //JBJB
	buffer.extend ((val   15).hexadecimal_digit);
	val := val >> 4;
      };
      old_count := buffer.count;
      {i >= old_count}.until_do {
	buffer.swap i with old_count;
	old_count := old_count - 1;
	i := i + 1;
      };
    };
    buffer.precede_multiple '0' by (s.to_integer - buffer.count);
  );

  - to_binary_in buffer:STRING format s:INTEGER <-
  // Append in `buffer' the equivalent of `to_binary_string'. No new STRING
  // creation during the process.
  // * Require: buffer not null
  [ -? {buffer!=NULL}; ]
  ( + val:SELF;
    + i,old_count:INTEGER;

    (Self = 0).if {
      buffer.extend '0';
    } else {
      i := buffer.count + 1;
      val := Self;
      {val != 0}.while_do {
	buffer.extend ('0' +# (val   1));
	val := val >> 1;
      };
      old_count := buffer.count;
      {i >= old_count}.until_do {
	buffer.swap i with old_count;
	old_count := old_count - 1;
	i := i + 1;
      };
    };
    buffer.precede_multiple '0' by ((s.to_integer) - buffer.count);
  );

  //
  // Hashing:
  //

  - hash_code:INTEGER <-
  // Hash code
  to_integer_32.hash_code; // BSBS:  Il faut revoir => Depending processor

  //
  // Print
  //

  - print <-
  // Print
  (
    (Self = 0).if {
      '0'.print;
    }.elseif {Self < 0} then {
      '-'.print;
      (-Self).print_positif;
    } else {
      print_positif;
    };
  );

  - print_positif <-
  // Display this number without memory.
  // * Require: Self >= 0
  [ -? {Self >=# 0}; ]
  ( + char:CHARACTER;
    + val:SELF;

    char := (Self % 10).decimal_digit;
    val  := Self / 10;
    (val != 0).if {
      val.print_positif;
    };
    char.print;
  );

  - print_hex <-
  // Display this number without memory.
  ( + char:CHARACTER;
    + val:SELF;

    char := (Self   0Fh).hexadecimal_digit;
    val  := Self / 16;
    (val != 0).if {
      val.print_hex;
    };
    char.print;
  );

  //
  // Debug manager facility.
  //

  - Self:SELF '?' blc:{BOOLEAN} <-  blc ?# Self;

Section INTEGER

  - to_raw_pointer:POINTER         <- CONVERT(UINTEGER_CPU,POINTER).on to_uinteger_cpu;