HaRe-0.6: tools/hs2alfa/tests/Integer.alfa
--#include "Alfa/Types.alfa"
--#include "Alfa/Bool.alfa"
--#include "Alfa/Natural.alfa"
--#include "Alfa/List.alfa"
--#include "Alfa/Tuples.alfa"
package Integers where
open Types use Digit, Sign, IntLit
open Booleans
use Bool, ifTrue, ifFalse, ifD, if_then_else, not, (&&),
(||), boolEq
open Natural
use Nat, succ, (+), (*), isZero, natRec, natEq, max, (-),
natLte, natLt, natGt
open Lists use List, reverse, null
open Tuples use Pair, fst, snd
Integer = IntLit
one = succ Zero@_
two = succ one
three = succ two
four = succ three
five = succ four
six = succ five
seven = succ six
eight = succ seven
nine = succ eight
digitToNat (d::Digit) :: Nat
= case d of {
(D0) -> Zero@_;
(D1) -> one;
(D2) -> two;
(D3) -> three;
(D4) -> four;
(D5) -> five;
(D6) -> six;
(D7) -> seven;
(D8) -> eight;
(D9) -> nine;}
isZeroDigit (d::Digit) :: Bool
= isZero (digitToNat d)
eqSign (s1::Sign)(s2::Sign) :: Bool
= case s1 of {
(Neg) ->
case s2 of {
(Neg) -> True@_;
(Pos) -> False@_;};
(Pos) ->
case s2 of {
(Neg) -> False@_;
(Pos) -> True@_;};}
eqDigit (d1::Digit)(d2::Digit) :: Bool
= natEq (digitToNat d1) (digitToNat d2)
eqDigits (ds1::List Digit)(ds2::List Digit) :: Bool
= case ds1 of {
(Nil) ->
case ds2 of {
(Nil) -> True@_;
(Cons x xs) -> False@_;};
(Cons x xs) ->
case ds2 of {
(Nil) -> False@_;
(Cons x' xs') -> (eqDigit x x' && eqDigits xs xs');};}
normDigits (ds::List Digit) :: List Digit
= case ds of {
(Nil) -> Nil@_;
(Cons x xs) ->
case isZeroDigit x of {
(True) -> normDigits xs;
(False) -> ds;};}
zeroInteger ::Integer
= Pair@_ Pos@_ (Cons@_ D0@_ Nil@_)
-- addSign: create +0 rather than -0
addSign (s::Sign)(ds::List Digit) :: Integer
= if_then_else Integer (null Digit ds) zeroInteger (Pair@_ s ds)
normInteger (i::Integer) :: Integer
= case i of { (Pair s ds) -> addSign s (normDigits ds);}
primNormIntegerEq (i1::Integer)(i2::Integer) :: Bool
= case i1 of {
(Pair s1 ds1) ->
case i2 of {
(Pair s2 ds2) ->
(eqSign s1 s2 && eqDigits (normDigits ds1) (normDigits ds2));};}
primIntegerEq (x::Integer)(y::Integer) :: Bool
= primNormIntegerEq (normInteger x) (normInteger y)
succDigit (d::Digit) :: Digit
= case d of {
(D0) -> D1@_;
(D1) -> D2@_;
(D2) -> D3@_;
(D3) -> D4@_;
(D4) -> D5@_;
(D5) -> D6@_;
(D6) -> D7@_;
(D7) -> D8@_;
(D8) -> D9@_;
(D9) -> D0@_;}
predDigit (d::Digit) :: Digit
= case d of {
(D0) -> D9@_;
(D1) -> D0@_;
(D2) -> D1@_;
(D3) -> D2@_;
(D4) -> D3@_;
(D5) -> D4@_;
(D6) -> D5@_;
(D7) -> D6@_;
(D8) -> D7@_;
(D9) -> D8@_;}
carryDigit (d::Digit) :: Bool
= case d of {
(D0) -> False@_;
(D1) -> False@_;
(D2) -> False@_;
(D3) -> False@_;
(D4) -> False@_;
(D5) -> False@_;
(D6) -> False@_;
(D7) -> False@_;
(D8) -> False@_;
(D9) -> True@_;}
borrowDigit (d::Digit) :: Bool
= case d of {
(D0) -> True@_;
(D1) -> False@_;
(D2) -> False@_;
(D3) -> False@_;
(D4) -> False@_;
(D5) -> False@_;
(D6) -> False@_;
(D7) -> False@_;
(D8) -> False@_;
(D9) -> False@_;}
succDigits (ds::List Digit) :: List Digit
= case ds of {
(Nil) -> Cons@_ D1@_ Nil@_;
(Cons x xs) ->
Cons@_ (succDigit x) (let it ::List Digit
= case carryDigit x of {
(True) -> succDigits xs;
(False) -> xs;}
in it);}
predDigits (ds::List Digit) :: List Digit
= case ds of {
(Nil) -> Nil@_;
(Cons x xs) ->
Cons@_ (predDigit x) (let it ::List Digit
= case borrowDigit x of {
(True) -> predDigits xs;
(False) -> xs;}
in it);}
incDigits (n::Nat)(ds::List Digit) :: List Digit
= case n of {
(Zero) -> ds;
(Succ n') -> succDigits (incDigits n' ds);}
decDigits (n::Nat)(ds::List Digit) :: List Digit
= case n of {
(Zero) -> ds;
(Succ n') -> predDigits (decDigits n' ds);}
mutual addDigits (ds1::List Digit)(ds2::List Digit) :: List Digit
= case ds1 of {
(Nil) -> ds2;
(Cons x xs) -> addDigits' xs (incDigits (digitToNat x) ds2);}
addDigits' (ds1::List Digit)(ds2::List Digit) :: List Digit
= case ds2 of {
(Nil) -> Cons@_ D0@_ ds1;
(Cons x xs) -> Cons@_ x (addDigits ds1 xs);}
addUnsigned (ds1::List Digit)(ds2::List Digit) :: List Digit
= reverse Digit (addDigits (reverse Digit ds1) (reverse Digit ds2))
O ::Set
= data LT | EQ | GT
lexOrd (o1::O)(o2::O) :: O
= case o1 of {
(LT) -> LT@_;
(EQ) -> o2;
(GT) -> GT@_;}
lte (o::O) :: Bool
= case o of {
(LT) -> True@_;
(EQ) -> True@_;
(GT) -> False@_;}
lt (o::O) :: Bool
= case o of {
(LT) -> True@_;
(EQ) -> False@_;
(GT) -> False@_;}
compareNat (n1::Nat)(n2::Nat) :: O
= if_then_else O (natLte n1 n2) (if_then_else O (natEq n1 n2) EQ@_ LT@_) GT@_
compareDigit (d1::Digit)(d2::Digit) :: O
= compareNat (digitToNat d1) (digitToNat d2)
compareDigits (ds1::List Digit)(ds2::List Digit) :: O
= case ds1 of {
(Nil) ->
case ds2 of {
(Nil) -> EQ@_;
(Cons x xs) -> LT@_;};
(Cons x xs) ->
case ds2 of {
(Nil) -> GT@_;
(Cons x' xs') -> lexOrd (compareDigits xs xs') (compareDigit x x');};}
compareUnsigned (ds1::List Digit)(ds2::List Digit) :: O
= compareDigits (reverse Digit ds1) (reverse Digit ds2)
compareNormInteger (i1::Integer)(i2::Integer) :: O
= case i1 of {
(Pair s1 ds1) ->
case i2 of {
(Pair s2 ds2) ->
case s1 of {
(Neg) ->
case s2 of {
(Neg) -> compareUnsigned ds2 ds1;
(Pos) -> LT@_;};
(Pos) ->
case s2 of {
(Neg) -> GT@_;
(Pos) -> compareUnsigned ds1 ds2;};};};}
compareInteger (i1::Integer)(i2::Integer) :: O
= compareNormInteger (normInteger i1) (normInteger i2)
primIntegerLte (i1::Integer)(i2::Integer) :: Bool
= lte (compareInteger i1 i2)
mutual subDigits (ds1::List Digit)(ds2::List Digit) :: List Digit
= case ds2 of {
(Nil) -> ds1;
(Cons x xs) -> subDigits' (decDigits (digitToNat x) ds1) xs;}
subDigits' (ds1::List Digit)(ds2::List Digit) :: List Digit
= case ds1 of {
(Nil) -> Nil@_;
(Cons x xs) -> Cons@_ x (subDigits xs ds2);}
posSubDigits (ds1::List Digit)(ds2::List Digit) :: List Digit
= reverse Digit (subDigits (reverse Digit ds1) (reverse Digit ds2))
subNormUnsigned (ds1::List Digit)(ds2::List Digit) :: Integer
= case lt (compareUnsigned ds1 ds2) of {
(True) -> Pair@_ Neg@_ (posSubDigits ds2 ds1);
(False) -> Pair@_ Pos@_ (posSubDigits ds1 ds2);}
subUnsigned (ds1::List Digit)(ds2::List Digit) :: Integer
= subNormUnsigned (normDigits ds1) (normDigits ds2)
primIntegerAdd (i1::Integer)(i2::Integer) :: Integer
= case i1 of {
(Pair s1 ds1) ->
case i2 of {
(Pair s2 ds2) ->
case s1 of {
(Neg) ->
case s2 of {
(Neg) -> Pair@_ Neg@_ (addUnsigned ds1 ds2);
(Pos) -> subUnsigned ds2 ds1;};
(Pos) ->
case s2 of {
(Neg) -> subUnsigned ds1 ds2;
(Pos) -> Pair@_ Pos@_ (addUnsigned ds1 ds2);};};};}
negateSign (s::Sign) :: Sign
= case s of {
(Neg) -> Pos@_;
(Pos) -> Neg@_;}
primIntegerNegate (i::Integer) :: Integer
= case i of { (Pair s ds) -> Pair@_ (negateSign s) ds;}
primIntegerSub (i1::Integer)(i2::Integer) :: Integer
= primIntegerAdd i1 (primIntegerNegate i2)
primIntegerAbs (i::Integer) :: Integer
= Pair@_ Pos@_ (snd Sign (List Digit) i)
primNormIntegerSignum (s::Sign)(ds::List Digit) :: Integer
= case ds of {
(Nil) -> Pair@_ Pos@_ (Cons@_ D0@_ Nil@_);
(Cons x xs) ->
case s of {
(Neg) -> Pair@_ Neg@_ (Cons@_ D1@_ Nil@_);
(Pos) -> Pair@_ Pos@_ (Cons@_ D1@_ Nil@_);};}
primIntegerSignum (i::Integer) :: Integer
= case i of { (Pair s ds) -> primNormIntegerSignum s (normDigits ds);}
mulDigit (n::Nat)(ds::List Digit) :: List Digit
= case n of {
(Zero) -> Nil@_;
(Succ n') -> addDigits ds (mulDigit n' ds);}
mulUnsigned (ds1::List Digit)(ds2::List Digit) :: List Digit
= case ds1 of {
(Nil) -> Nil@_;
(Cons x xs) ->
addDigits (mulDigit (digitToNat x) ds2) (mulUnsigned xs (Cons@_ D0@_ ds2));}
mulSign (s1::Sign)(s2::Sign) :: Sign
= case s1 of {
(Neg) -> negateSign s2;
(Pos) -> s2;}
primIntegerMul (i1::Integer)(i2::Integer) :: Integer
= case i1 of {
(Pair s1 ds1) ->
case i2 of {
(Pair s2 ds2) ->
Pair@_ (mulSign s1 s2) (reverse Digit (mulUnsigned (reverse Digit ds1) (reverse Digit ds2)));};}
postulate primIntegerRem :: Integer -> Integer -> Integer
postulate primIntegerQuot :: Integer -> Integer -> Integer
{-# Alfa unfoldgoals off
brief on
hidetypeannots off
wide
nd
hiding on
var "eqSign" infix 4 as "=="
var "eqDigit" infix 4 as "=="
var "eqDigits" infix 4 as "=="
#-}