#!/usr/bin/perl -w

my $ans = "0"x32;
my @func = (undef,"conv_x","add_x","sous_x","mul_x","div_x",sub {exit});



sub clear()
{
    print "\e[2J";	# clear screen 
    print "\e[1,1H";	# position 1,1
}


sub menu()
{
$rep = 0;
while($rep ne "6")
{
    print <<_EOF_MENU_;
    

    /\\_______.oOo. \e[1mCalculatrice Binaire\e[0m .oO__________/\\
    |                                                 |
    |   \e[1m1\e[0m     -   Convertir un entier en binaire      |
    |   \e[1m2\e[0m     -   Addition binaire                    |
    |   \e[1m3\e[0m     -   Soustraction binaire                |
    |   \e[1m4\e[0m     -   Multiplication binaire              |
    |   \e[1m5\e[0m     -   Division binaire                    |
    |   \e[1m6\e[0m     -   Sortir                              |    
    \\_________________________________________________/


_EOF_MENU_
affichage($ans);
my $rep = &lecture;
if ($rep) { &programme($rep); }
}
}



sub lecture()
{
    print "Veuillez entrer un choix entre 1 et 6 : ";
    my $entree = <STDIN>;
    chomp($entree);
    while ($entree !~ /^[123456]$/)
    {
	print "Choix incorrect \"$entree\" (de 1 a 6) : Veuillez reentrer un choix.\n";
	$entree = <STDIN>;
        chomp($entree);	
    }
    return $entree;

}


sub programme($)
{
    my $prop = shift;
    $ans = &{$func[$prop]};
}









sub entrer_bin()
{
my $num;
    do
    {
        print "Entrer un entier binaire (sur 32 bits : 1_8_23 ): ";
        $num = <STDIN>;
	chomp($num);	
    }
    until ($num =~ /^[01]{32}$/);
return $num;
}






sub sous_x()
{
    &clear;
    my $ia = entrer_bin();
    my $ib = entrer_bin();
    $ans = sous($ia,$ib);    
}






sub add_x()
{
    &clear;
    print "Additionner $ans avec : \n";
    my $ib = entrer_bin();
    $ib = normalise($ib);
    &clear;
    print "\t$ans \n+\t$ib\n";
    print "_"x40;
    print "\n";
    $ans = add($ans,$ib);    
}



sub sous($$)
{
my $ia = shift;
my $ib = shift;
print "Sous de $ia - $ib\n";
my @p = reverse split("",$ia);
my @d = reverse split("",$ib);

for (scalar @p.. 31) { push(@p,"0"); }
for (scalar @d.. 31) { push(@d,"0"); }

$retenue=0;
for (0..31)
{
    $somme = $p[$_] - $d[$_] + $retenue;
    $retenue  = $somme < 0 ? -1 : 0;
    $resultat[$_] = abs($somme);
}

return join("",reverse @resultat);



}





sub add($$)
{
my $ia = shift;
my $ib = shift;
my ($as,$bs,$ae,$be,$am,$bm); # a_signe a_exposant a_mantisse ...
$ia =~ /(\d)(\d{8})(\d{23})/ && do { ($as,$ae,$am) = ($1,$2,$3); };
$ib =~ /(\d)(\d{8})(\d{23})/ && do { ($bs,$be,$bm) = ($1,$2,$3); };

if ($as == 0 && $bs == 1)
{
    $bs = 0;
    return sous($ia,$bs.$be.$bm);
}
if ($as == 1 && $bs == 0)
{
    $as = 0;
    return sous($ib,$as.$ae.$am);
}

print "Difference des exposants biaises : ";
print "$ae et $be\n";
print "MANTISSES: AM $am et BM $bm\n";
if ($ae > $be)
{
    print "AE > BE \n";
    my @ae = reverse split//,$ae;
    my @be = reverse split//,$be;    
    print "@ae : "; print @ae ; print "\n";
    print "@be : "; print @be ; print "\n";
    $dacalage = 0;
    $i=0;
    while ($ae != $be)
    {
    @be = reverse split//,$be;
    $decalage++;    
    print "$ae != $be\n";
    $be[$i]++;
    while($be[$i] > 1)
    {
	print "$be[$i] > 1\n";
	$be[$i]=0;
	$be[$i+1]++;
	$i++;

    }
    $be = join("", reverse @be);
    
}
print "DECALAGE DE BM :";
$bm = decal_gauche($bm,$decalage);

}
else 
{
    print "BE > AE \n";
    my @ae = reverse split//,$ae;
    my @be = reverse split//,$be;    
    print "@ae : "; print @ae ; print "\n";
    print "@be : "; print @be ; print "\n";
    $dacalage = 0;
    $i=0;
    while ($ae != $be)
    {
    @ae = reverse split//,$ae;
    $decalage++;    
    print "$ae != $be\n";
    $ae[$i]++;
    while($ae[$i] > 1)
    {
	print "$ae[$i] > 1\n";
	$ae[$i]=0;
	$ae[$i+1]++;
	$i++;

    }
    $ae = join("",reverse @ae);
    }
    print "DECALAGE DE AM :";
    $am =decal_gauche($am,$decalage);
}

print "FINAL $am et $bm \n";
my $retenue = $ans;


return 0;
}


sub decal_gauche($$)
{
my $decalage = shift;
my $nombre = shift;
print "Decalage de $decalage  de  $nombre a gauche\n";

@decalage = split //,$decalage;
push(@decalage,1);
$nombre--;
for(1..$nombre)
{
    push(@decalage,0);
}
return join("",return @decalage[0..22]);



}





sub conv_x()
{
    &clear;
    my $num = entrer_int();
    $ans = int2bin($num);
}




sub entrer_int()
{
my $num;
    do
    {
        print "Entrer un entier reel: ";
        $num = <STDIN>;
	chomp($num);	
    }
    until ($num =~ /^\-?[0-9]+(?:\.[0-9]+)?$/);
return $num;
}



sub normalise($)
{
$num = shift;
$long = split("",$num);
for ($long .. 31) { $num = "0".$num; }
print "FIN $num\n";
return $num;

}







sub int2bin($)
{
    my $num = shift;;
    my @arr;
	
    undef($virgule);
    if ($num =~ /\.(\d+)$/) { $virgule = "0.".$1;  }
    else {$virgule = "0"; }
    
    
    $signe = $num > 0 ? 0 : 1;
    if ($signe) { $num*=-1; }
    my @bin;
    while ($num > 1)
    {
        push(@bin,($num%2));
        $num=int($num/2);
    }	

    push(@bin,$num);
    my $puissance = (scalar @bin)-1;



    @bin = reverse @bin;
    my @virg;
    for ($puissance .. 22)
    {
        $virgule = $virgule * 2;
        if ($virgule >= 1)  { $virgule -=1; @virg = ("1",@virg); }
        else { @virg=("0",@virg); }
    }

    @bin = (@bin,reverse @virg);
    shift(@bin);

    my $exp=127+$puissance;
    my $i="";
    
    for (1..7)
    {
#    while($exp > 1)
#    {	
        $i=($exp % 2)."$i";
        $exp=int($exp/2);
    }
    $i=$exp."$i";
    $retour =$signe.$i.join("",@bin);
    print "Signe $signe\n";
    print "Expossant : $exp = $i ";
    print "Mantisse ".join("",@bin)."\n";
    return $retour;
}
    





sub affichage($)
{
my $num = shift;
$num =~ /(\d)(\d{8})(\d{23})/ && print "Recu :\t$1 $2 $3\n\n"; 
}






&clear();
&menu();



