package kvec;

use 5.006;
use strict;
use warnings;
use Data::Dumper;
require Exporter;

our @ISA = qw(Exporter);

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration	use kvec ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
	
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(new set_pieces set_lcutOff set_ucutOff p2n3 p2n3_align calcStat set_statistic printToFile printStdOut
);
our $VERSION = '0.03';


# Preloaded methods go here.

#funcao para calcular o no de partes do texto

sub new
{
	my $self={};
	bless $self;
	
	shift;
	my $tam=@_;
	$self->{"lcutOff"}=5;
	$self->{"ucutOff"}=10000;
 	$self->{"statistic"}="calculateRightFisher";	
	if ($tam==1)
	{
		my $file=shift;
		$self->fromFile($file);
	}
	elsif ($tam==2)
	{
		my $src=shift;
		my $trg=shift;
		
		$self->{"sourceFile"}=$src;
		$self->{"targetFile"}=$trg;
		$self->p2n3();
	}
	elsif ($tam==3)
	{
		my $h=shift;
		my $src=shift;
		my $trg=shift;
		if (defined $h->{'lcutOff'})
		{
			$self->{"lcutOff"}=$h->{'lcutOff'};
		}
		if (defined $h->{'ucutOff'})
		{
			$self->{"ucutOff"}=$h->{'ucutOff'};
		}
		if (defined $h->{'pieces'})
		{
			$self->{'pieces'}=$h->{'pieces'};
		}
		if (defined $h->{'aligned'})
		{
			$self->p2n3_align();
		}
		else
		{
			$self->p2n3();
		}
	}
	return $self
}

sub fromFile
{
	my $self=shift;
	my $file=shift;
	my @tokens;
	my @numbers;
	open(A,$file) or die "file $file not found\n";
	my $temp=<A>;
	chomp $temp;
	$self->{'pieces'}=$temp;
	while(<A>)
	{
		chomp($_);
		@tokens=split(/<>/,$_);
		@numbers=split(/ /,$tokens[2]);
		$self->{'hashSourceWords'}{$tokens[0]}=$numbers[1];
		$self->{'hashTargetWords'}{$tokens[1]}=$numbers[2];
		$self->{'pairsHash'}{"$tokens[0] $tokens[1]"}=$numbers[0];
	}
	
	

}

sub grep
{
	my $self=shift;
	my @words=@_;
	my %newSrcHash;
	my %newTrgHash;
	my %newPairs;
	my @tokens;
	my $pares;
	my $newP2N3=new kvec();
	my $tempHash=$self->{'pairsHash'};

	for (@words)
	{
		if (defined $self->{'hashSourceWords'}{$_})
		{
			$newSrcHash{$_}=$self->{'hashSourceWords'}{$_};
		}
		for $pares(keys %{$tempHash})
		{
			@tokens=split(/ /,$pares);
			if ($_ eq $tokens[0])
			{
				$newPairs{$pares}=$self->{'pairsHash'}{$pares};
				$newTrgHash{$tokens[1]}=$self->{'hashTargetWords'}{$tokens[1]};
			}
		}
	}
	$newP2N3->{'hashSourceWords'}=\%newSrcHash;
	$newP2N3->{'hashTargetWords'}=\%newTrgHash;
	$newP2N3->{'pairsHash'}=\%newPairs;
	$newP2N3->{'pieces'}=$self->{'pieces'};

	return $newP2N3;
	
	
	
}
############################################################
sub filter
{
}
############################################################

sub sum
{
	my $self=shift;
	my $other=shift;
	my $value;
	
	my $tempHash=$other->{'hashSourceWords'};

	$self->{'pieces'}+=$other->{'pieces'};
	for(keys  %$tempHash)
	{
		$value=$other->{'hashSourceWords'}{$_};
		$self->{'hashSourceWords'}{$_}+=$value;
	}
	$tempHash=$other->{'hashTargetWords'};
	for(keys  %$tempHash)
	{
		$value=$other->{'hashTargetWords'}{$_};
		$self->{'hashTargetWords'}{$_}+=$value;
	}
	$tempHash=$other->{'pairsHash'};
	for(keys  %$tempHash)
	{
		$value=$other->{'pairsHash'}{$_};
		if (defined $self->{'pairsHash'}{$_})
		{
			$self->{'pairsHash'}{$_}+=$value;
		}
		else
		{
			$self->{'pairsHash'}{$_}=$value;
		}
	}
}


sub set_statistic
{
	my $st={
		   "right fisher"       => "calculateRightFisher",
		   "log likelihood"     => "calculateLL",
		   "dice"	        => "calculateDice",
		   "mutual information" => "calculateMI",
		   "odds ratio"		=> "calculateOdds",
		   "t-score"		=> "calculateTscore"
	   };
	
	my $self=shift;
	my $stat=shift;
	$stat=lc($stat);
	if (defined $st->{$stat})
	{
		
		$self->{"statistic"}=$st->{$stat};
	}
	else 
	{
		print STDERR "Statistic package not defined!\n";
		exit 0;
	}
}
	   
		

sub set_pieces
{
	my $self=shift;
	my $pieces=shift;
	$self->{"pieces"}=$pieces;
}

sub set_lcutOff
{
	my $self=shift;
	my $lcutOff=shift;
	$self->{"lcutOff"}=$lcutOff;
}

sub set_ucutOff
{
	my $self=shift;
	my $ucutOff=shift;
	$self->{"ucutOff"}=$ucutOff;
}

sub p2n3
{
	my $self=shift;
	my $sourceFile=$self->{"sourceFile"};
	my $targetFile=$self->{"targetFile"};
	my %sourceHash;
	my %targetHash;
	my @sourceArray;
	my @targetArray;
	my $i;
	my $pieces;
	my %pairsHash;
	my %sourceWords;
	my %targetWords;
	
	$self->{"sourceWords"}=&calculateWords($sourceFile,\%sourceHash);
	$self->{"targetWords"}=&calculateWords($targetFile,\%targetHash);
	$self->{"sourceHash"}=\%sourceHash;
	$self->{"targetHash"}=\%targetHash;
	$self->calculatePieces();
	$self->createPieces(\@sourceArray,$sourceFile,$self->{"Source_words_per_piece"},$self->{"pieces"});
	$self->createPieces(\@targetArray,$targetFile,$self->{"Target_words_per_piece"},$self->{"pieces"});
	$self->{"sourceArray"}=\@sourceArray;
	$self->{"targetArray"}=\@targetArray;
	$self->make_pairs();
		
}
sub p2n3_align
{
	my $self=shift;
	my $sourceFile=$self->{"sourceFile"};
	my $targetFile=$self->{"targetFile"};
	my %sourceHash;
	my %targetHash;
	my @sourceArray;
	my @targetArray;
        $self->{"sourceWords"}=&calculateWords($sourceFile,\%sourceHash);
        $self->{"targetWords"}=&calculateWords($targetFile,\%targetHash);
        $self->{"sourceHash"}=\%sourceHash;
        $self->{"targetHash"}=\%targetHash;
	$self->{"pieces"}=&countPieces($self->{"sourceFile"});
	$self->createPiecesAlign(\@sourceArray,$self->{"sourceFile"});
	$self->createPiecesAlign(\@targetArray,$self->{"targetFile"});
        $self->{"sourceArray"}=\@sourceArray;
        $self->{"targetArray"}=\@targetArray;
			
	$self->make_pairs();		
}

sub make_pairs
{
	my $self=shift;
	my $pieces=$self->{"pieces"};
	my $i;
	my %pairsHash;
	my %targetWords;
	my %sourceWords;
	for ($i=0;$i<$pieces;$i++)
	{
		#######################################################
		my $hrefSource=$self->{"sourceArray"}[$i]; 
		my $hrefTarget=$self->{"targetArray"}[$i];
		########### FAZER UNDEF A ESTAS  HASHS NO FIM DESTA FUNCAO
		$self->makePairs($hrefSource, $hrefTarget, \%pairsHash, \%sourceWords, \%targetWords);
	}
	$self->{"pairsHash"}=\%pairsHash;
	$self->{"hashSourceWords"}=\%sourceWords;
	$self->{"hashTargetWords"}=\%targetWords;
	undef $self->{"targetArray"};
	undef $self->{"sourceArray"};
}

sub createPiecesAlign
{
        my $self=shift;
	my $refArray = $_[0];
        my $fileName = $_[1];
        my $i=0;
	my $line;
	my $out;
	my @wordArray;
        open(FILE, $fileName ) || die "Error opening $fileName";
        while ( $line = <FILE> )
        {
		$line =~ tr/A-Z/a-z/;
        	$line = &removeSpaces($line);
        	@wordArray=split(/ /,$line);
        	foreach $out(@wordArray)
        	{
			$refArray->[$i]{$out}++;
		}
		$i++;
	}
}																																																	
sub countPieces

{
        my $fich=shift;
        my $c=0;
        open (A,$fich);
        while(<A>)
        {
	        $c++;
	}
        return $c;
}
													
sub calculatePieces #falta ver quais sao os argumentos
{
	
	my $self=shift;
	my $sourcePieces;
	my $targetPieces;
	my $Source_words_per_piece;
	my $Target_words_per_piece;
	if ( defined $self->{"pieces"} )
	{
		if($self->{"pieces"} == 0)
		{
			print "Number of pieces should be greater than zero\n";
			exit;
		}
		$sourcePieces = $self->{"pieces"};
		$targetPieces = $self->{"pieces"};
		$Source_words_per_piece = $self->{"sourceWords"} / $sourcePieces;
		$Target_words_per_piece = $self->{"targetWords"} / $targetPieces;
	}
	else
	{
		$sourcePieces = sqrt( $self->{"sourceWords"} );
		$sourcePieces = &floorCeil($sourcePieces);
		$Source_words_per_piece = $self->{"sourceWords"} / $sourcePieces;
		$targetPieces = $sourcePieces;
		$Target_words_per_piece = $self->{"targetWords"}/$targetPieces;
	}

	$self->{"pieces"} = $sourcePieces;
	$Source_words_per_piece = &floorCeil($Source_words_per_piece);
	$Target_words_per_piece = &floorCeil($Target_words_per_piece);
	$self->{"Source_words_per_piece"}=$Source_words_per_piece;
	$self->{"Target_words_per_piece"}=$Target_words_per_piece;
								   
}

sub calculateWords #Devolve o no de palavras num texto
{
	my $line;
	my $wordCount;
	my $word;
	my $fileName = $_[0];
	my $refHash = $_[1];
	my @wordArray;
    	# checks if the file exists !! 
	if( ! (-e $fileName ) )
	{
		print "\nERROR!!! $fileName not found\n ";
		exit;
        }
	 open(FILE, $fileName) || die "Error opening $fileName";
	 while( $line = <FILE>)
	 {
         	$line = &removeSpaces($line);
         	$line =~ tr/A-Z/a-z/;  #Converte tudo para minusculas
         	@wordArray = split(/\s+/,$line);
	         $wordCount += @wordArray;
		 foreach $word(@wordArray)
		 {
		 	$refHash->{$word}++;
		 }
	 	undef(@wordArray);
	}
	close(FILE);
	return($wordCount);
}
						      

sub deleteHash
{
	my $self=shift;
	my $word;
	my %tempHash = %{$self->{"pairsHash"}};
	my $lcutOff=$self->{"lcutOff"};
	my $ucutOff=$self->{"ucutOff"};

	foreach $word( sort keys %tempHash )
	{
		if( $tempHash{$word} < $lcutOff )
		{
			delete($tempHash{$word});
		}
		elsif( $tempHash{$word} > $ucutOff )
		{
			delete($tempHash{$word});
		}
	}
	$self->{"pairsHash"}=\%tempHash;
}

sub floorCeil
{
	my $x=0;
	$x = sprintf(" %d ", $_[0]);
	return $x;
}

sub createPieces
{
	
	my $self=shift;
	my $pieceNumber = 0;
	my $totalWords = 0;
	my $refArray = $_[0];
	my $fileName = $_[1];
	my $length = $_[2];
	my $totalPieces = $_[3];
	my @wordArray = ();
	my $line;
	my $p=0;
	my $out;
	my $pieces = $self->{"pieces"};
	open(FILE, $fileName ) || die "Error opening $fileName";
	while ( $line = <FILE> )
	{
		$line =~ tr/A-Z/a-z/;
		$line = &removeSpaces($line);
		# stores all the space seperated words in an array
		@wordArray = (@wordArray, split(/ /,$line ) );
		while($#wordArray >= $length)
		{
			#if loop added on 12-28-2001
			if($pieceNumber >= $totalPieces)
			{
				last;
			}
			#if loop added on 12-28-2001
			for($p=0;$p<$length;$p++)
			{
				($out, @wordArray) = @wordArray;
				$refArray->[$pieceNumber]{$out}++
			}
			$pieceNumber++;
		}
	}

# Once the whole file is read, it just concatenates all the words remaining
# in the array to the last piece and also stores each word in the hash
	if($pieceNumber >= $pieces)
	{
		$pieceNumber--;
	}
	foreach $out(@wordArray)
	{
		$refArray->[$pieceNumber]{$out}++;
	}
	close(FILE);
						 
}						 




sub removeSpaces{

	$_[0] =~ tr/A-Z/a-z/;
	$_[0] =~ s/[\/\|\(\)\[\]\{\}\^\$\*\+\?\.\,\"\-\\\:0-9%]//g;
	$_[0] =~ s/^\s+//g;
	$_[0] =~ s/\s+$//g;
	$_[0] =~ s/\s+/ /g;
	$_[0] =~ s/\n+//g;
	return $_[0];
}


sub makePairs{

    my $self=shift;
    my $hrefSourcehash = $_[0];
    my $hrefTargethash = $_[1];
    my $refPairs = $_[2];
    my $refSourcewords = $_[3];
    my $refTargetwords = $_[4];
    my $word1;
    my $word2;
    my $pair;
    my %temphash;
    my %sourceHash=%{$self->{"sourceHash"}};   
    my %targetHash=%{$self->{"targetHash"}};
    foreach $word1(keys %$hrefSourcehash)
    {
	if(exists $sourceHash{$word1})
	{
		$refSourcewords->{$word1}++;
		foreach $word2(keys %$hrefTargethash)
		{
	        	if(exists $targetHash{$word2})
	                {
		        	if(!(exists $temphash{$word2}))
		                {
			        	$refTargetwords->{$word2}++;
			        }
			        $temphash{$word2}++;
			        $pair = $word1." ".$word2;
			        $refPairs->{$pair}++;
			}
		}
	}
    }
}

sub printToFile
{
	my $self=shift;
	my $file=shift;
	my $refpairs = $self->{"pairsHash"};
	my $refSource = $self->{"hashSourceWords"};
	my $refTarget = $self->{"hashTargetWords"};
	my $i=0;
	my $pairs;
	my $pieces=$self->{"pieces"};
	my $word1;
	my $word2;
	open(DST,">$file");
	#$self->deleteHash();
	
    	$pieces =~ s/\s+//g;
	$pieces = $pieces;
	print DST "$pieces";
	foreach $pairs(keys %$refpairs)
	{
		($word1, $word2) = split(/ /,$pairs);
		print DST "\n$word1<>$word2<>$refpairs->{$pairs} $refSource->{$word1} $refTarget->{$word2}";
	}
	print DST  "\n";

}
sub printStdOut
{
        my $self=shift;
        my $refpairs = $self->{"pairsHash"};
        my $refSource = $self->{"hashSourceWords"};
        my $refTarget = $self->{"hashTargetWords"};
        my $i=0;
        my $word1;
        my $word2;
        my $pairs;
        #$self->deleteHash();
        my $pieces=$self->{"pieces"};
        $pieces =~ s/\s+//g;
        $pieces = $pieces;
        print "$pieces";
        foreach $pairs(keys %$refpairs)
        {
	        ($word1, $word2) = split(/ /,$pairs);
                print "\n$word1<>$word2<>$refpairs->{$pairs} $refSource->{$word1} $refTarget->{$word2}";
        }
        print  "\n";
}
																					
sub printToString
{
	my $self=shift;
	my $refpairs=$self->{"pairsHash"};
        my $refSource = $self->{"hashSourceWords"};
        my $refTarget = $self->{"hashTargetWords"};
        my $i=0;
        my $word1;
	my $pairs;
        my $word2;
        my $pieces=$self->{"pieces"};
        my $result="";
        #$self->deleteHash();
        $pieces =~ s/\s+//g;
        $pieces = $pieces;
        $result.= "$pieces";
        foreach $pairs(keys %$refpairs)
        {
                ($word1, $word2) = split(/ /,$pairs);
                $result.= "\n$word1<>$word2<>$refpairs->{$pairs} $refSource->{$word1} $refTarget->{$word2}";
        }
        $result.=  "\n";
	return $result;
}
																						
						     




sub calcStat
{
	my $self=shift;
	my $floatFormat = join '', '%', '.', 4, 'f';
	my $statistic = $self->{"statistic"};
	my $destination = "";
	my $p2n3 = ${$self->{"p2n3"}};
	my @linhas=split(/\n/,$p2n3);
	my $flag = 1;
	my $lineNo = 0; # will tell us where in the source file we have a problem!
	my $wordTotal = shift @linhas;
	my @tokens;
	my $ngramSize;
	my @numbers;
	my $i;
	my %STATISTIC;
	my @individualFreq;
	my %ngramFreq;
	for (@linhas )
	{
		$lineNo++;
		chomp $_;
		@tokens = split(/<>/, $_);
		$ngramSize = $#tokens;
		@numbers = split(/ /, $tokens[$#tokens]);
		pop @tokens;
		#$tokens[0] =~ s/^@@/@/; 
		# now create the hashes for the individual word freqs
		for ($i = 0; $i < $ngramSize; $i++)
		{
			$individualFreq[$i]->{$tokens[$i]} = $numbers[$i+1];
		}
		# otherwise create the ngram string...
		my $ngramString = join("<>", @tokens);
		# construct the ngram frequency hash, necessary for printing later.
		$ngramFreq{$ngramString} = $numbers[0];
		# calculate the statistic and create the statistic hash. the
		# calculateStatistic function has to be implemented by the statistic
		# library.      
		$STATISTIC{$ngramString} = $self->$statistic(@numbers, $wordTotal);
		$STATISTIC{$ngramString} = sprintf $floatFormat, $STATISTIC{$ngramString};
	}

	chomp $wordTotal;
	$destination.= "$wordTotal\n";
	my $rank = 0;
	my $lastValue = 0;
	foreach ( sort { $STATISTIC{$b} <=> $STATISTIC{$a} } keys %STATISTIC )
	{
		my @tokens = split ( /<>/, $_ );
		if ( $lastValue != $STATISTIC{$_} )
		{
			$lastValue = $STATISTIC{$_};
			$rank++;
		}
		# do bit-stuffing
		#if ( $_ =~ /^@/ ) { $destination.= "@"; }
		$destination.= "$_<>";
		chomp $rank;
		$destination.= "$rank ";
		chomp $STATISTIC{$_};
		$destination.= $STATISTIC{$_};
		chomp $ngramFreq{$_};
		$destination.=" $ngramFreq{$_} ";
		for ($i = 0; $i < $ngramSize; $i++)
		{
			chomp $individualFreq[$i]->{$tokens[$i]};
			$destination.="$individualFreq[$i]->{$tokens[$i]}";
			if ($i < $ngramSize-1) { $destination.= " "; }
		}
		$destination.= "\n";
	}
	return $destination;

}




sub calculateRightFisher
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
        my $n11 = $freq;
	my $npp = $totalBigrams;
	my $n1p = $freq1;
        my $np1 = $freq2;
        my $n2p = $npp - $n1p;
        my $np2 = $npp - $np1;
        # we shall have two arrays one for the numerator and one for the
        # denominator. the arrays will contain the factorial upper limits. we
        # shall be arrange these two arrays in descending order. while doing the
        # actual calculation, we shall take a numerator/denominator pair, and
        # go from the lower value to the higher value, in effect doing a
        # "cancellation" of sorts.
        # first create the numerator
        my @numerator = sort { $b <=> $a } ($n1p, $np1, $n2p, $np2);

        # now to the real calculation!!!
        my $probability = 0;
        my $i;
        my $j;
        # we shall calculate for n11 = 0. thereafter we shall just multiply and
        # divide the result for 0 with correct numbers to obtain result for i,
        # i>0, i<=n11!! :o)
        my $lower_limit = $n11;
	my $upper_limit;
        if($freq1 > $freq2)
        {
	        $upper_limit = $freq2;
	}
	else
	{
		$upper_limit = $freq1;
	}
	my $n12 = $n1p-$n11;
        my $n21 = $np1-$n11;
	my $n22 = $n2p - $n21;
	while($n22 < 0 or $n12 < 0 or $n21 < 0)
	{
		$n11++;
		$n12 = $n1p - $n11;
		$n21 = $np1 - $n11;
	        $n22 = $n2p - $n21;
        }
        my @denominator = sort { $b <=> $a } ($npp, $n22, $n12, $n21, $n11);
        # now that we have our two arrays all nicely sorted and in place,
        # lets do the calculations!
        my @dLimits = ();
        my @nLimits = ();
        my $dIndex = 0;
        my $nIndex = 0;
        for ( $j = 0; $j < 4; $j ++ )
        {
	        if ( $numerator[$j] > $denominator[$j] )
		{
        		$nLimits[$nIndex] = $denominator[$j] + 1;
			$nLimits[$nIndex+1] = $numerator[$j];
        	$nIndex += 2;
        	}
	        elsif ( $denominator[$j] > $numerator[$j] )
	        {
    	        	$dLimits[$dIndex] = $numerator[$j] + 1;
	                $dLimits[$dIndex+1] = $denominator[$j];
	                $dIndex += 2;
                }
	}
	$dLimits[$dIndex] = 1;
	$dLimits[$dIndex+1] = $denominator[4];
        my $product = 1;
        while ( defined ( $nLimits[0] ) )
        {
	        while ( ( $product < 10000 ) && ( defined ( $nLimits[0] ) ) )
	        {
        	        $product *= $nLimits[0];
			$nLimits[0]++;
	                if ( $nLimits[0] > $nLimits[1] )
     	                {
		                shift @nLimits;
		                shift @nLimits;
		        }
	        }
                while ( $product > 1 )
	        {
	                $product /= $dLimits[0];
	                $dLimits[0]++;
	                if ( $dLimits[0] > $dLimits[1] )
        	        {
		                shift @dLimits;
		                shift @dLimits;
                        }
                }
        }
        while ( defined ( $dLimits[0] ) )
        {
	        $product /= $dLimits[0];
	        $dLimits[0]++;
  	        if ( $dLimits[0] > $dLimits[1] )
	        {
                shift @dLimits;
                shift @dLimits;
	        }
        }
	# $product now has the hypergeometric probability for n11 = 0. add it to
        # the cumulative probability
        $probability += $product;
        # now for the rest of n11's !!
        for ( $i = $n11+1; $i <=  $upper_limit; $i++ )
        {
	        $product *= $n12;
	        $n22++;
	        $product /= $n22;
	        $product *= $n21;
	        $n12--;
	        $n21--;
	        $product /= $i;
	
		# thats our new probability for n11 = i! :o)) cool eh? ;o))
	        # add it to the main probability! :o))

		$probability += $product; # !! :o)
        }
										        # thats abt it!
        return (1-$probability);

}

sub calculateDice
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
	return (2 * $freq / ( $freq1 + $freq2 ));
}

sub calculateLL
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
        my $n11 = $freq;       # pair freq
	my $n1p = $freq1;      # single freq of first word
        my $np1 = $freq2;      # single freq of second word
	my $n12 = $n1p - $n11;
        my $n21 = $np1 - $n11;
        my $np2 = $totalBigrams - $np1;
        my $n2p = $totalBigrams - $n1p;
        my $n22 = $np2 - $n12;
        my $npp = $totalBigrams;
	my $m11 = $n1p * $np1 / $npp;
        my $m12 = $n1p * $np2 / $npp;
        my $m21 = $n2p * $np1 / $npp;
        my $m22 = $n2p * $np2 / $npp;
        my $logLikelihood = 0;
        if ( $n11 ) { $logLikelihood += $n11 * log ( $n11 / $m11 ); }
        if ( $n12 ) { $logLikelihood += $n12 * log ( $n12 / $m12 ); }
        if ( $n21 ) { $logLikelihood += $n21 * log ( $n21 / $m21 ); }
        if ( $n22 ) { $logLikelihood += $n22 * log ( $n22 / $m22 ); }
        return ( 2 * $logLikelihood );
}	

sub calculateMI
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
        my $temp = ( $freq / $freq1 ) / $freq2;
        $temp *= $totalBigrams;		        
	return ( log($temp) / log(2) );
}

sub calculateOdds
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
	my $a = $freq;
	my $b = $freq1 - $a;
	my $c = $freq2 - $a;
	my $d = ($totalBigrams - $a - $b - $c);
	if(($b == 0) and ($c == 0))
	{
		return ($a*$d);
	}
	elsif($b ==0 and $c!=0)
	{
	        return((($a)*($d))/($c));
	}
        elsif($b!=0 and $c==0)
        {
        	return((($a)*($d))/($b));
	}
        else
        {
     		my $OR = ( ($a * $d) / ($b * $c) );
	        return($OR);
        }
}

sub calculateTscore
{
	shift;
	my ($freq, $freq1, $freq2, $totalBigrams) = @_;
	my $pairFreq =  $freq/$totalBigrams;
	my $word1Freq = $freq1/$totalBigrams;
        my $word2Freq = $freq2/$totalBigrams;
        my $numerator = $pairFreq - ($word1Freq * $word2Freq);
        my $denominator = sqrt(($pairFreq/$totalBigrams));
        return ( ( $numerator / $denominator ) );
}
			    
		






1;
__END__
# Below is stub documentation for your module. You better edit it!

=head1 NAME

kvec - Perl extension for extraction of bilingual terminology

=head1 ABSTRACT



=head1 SYNOPSIS

  use kvec;
  
  $file1=shift;
  $file2=shift;
  
  $a=new kvec($file1,$file2);

  $a->printTofile("a.tmp");
  print $result;
  


=head1 DESCRIPTION


=head2 METHODS

B<new>

Creates a new instance of kvec object. You can use it in 3 diferent ways:

With 2 parameters (the files you want to open):

	$a->new kvec($file1.$file2)

With 1 paramameter, if you want to open a file with the result of a previous calling to kvec 

	$a->new kvec($file)

With 3 parameters if you want to open 2 files wiht extra parameters

	$a->new kvec({pieces	=> 45,
		      lcutOff => 5,
		      ucutOff => 1000
		      align   => 1}, $file1, $file2);

C<pieces> - is the number of pieces you want to divide the texts.

C<lcutOff> - the words with a frequency below this value aren't used .

C<ucutOff> - the words with a frequency higher than this value aren't used.

C<align> - you should use this value if the texts you are using are aligned in some sort of way. It does not make sense to use this value and C<pieces> at the same time.

B<printToFile> 

Prints the result to file 

	$a->printToFile($outfile);

B<printToString>

Returns the result as a string

	$result->$a->printToString();

B<grep>

Returns a new object, but only with the result of a list of words

	$b=$a->grep($word1,$word2,...,$wordn)

B<sum>

With this method you can "sum" the result of 2 kvec objects

		$a->new kvec($file1,$file2);
		$b->new kvec($file3,$file4);
		$a->sum($b);
	

B<set_statistic>

Sets the statistic test you want to use. If you don't call this method, the statistic test used by default is the I<Right Fisher>. The other available tests are I<Log Likehihood>, I<T-score>, I<Dice> and I<Odds ratio>. 



B<calcStat>

This method calculates the dependence between words  using the chosen statistic test and returns the result as a string.



=head1 HISTORY

=over 8

=item 0.01

Original version; created by h2xs 1.21 with options

  -A
	-C
	-X
	-c
	-n
	kvec

=back


=head1 AUTHOR

Ted Pedersen, E<lt>tpederse@d.umn.eduE<gt>

Nitin Varma, E<lt>varm0003@d.umn.eduE<gt>

Bruno Martins, E<lt>bsm@natura.di.uminho.ptE<gt>

=head1 SEE ALSO

L<perl>.


Fung. P. & K. W. Church. (1994) "K-vec: A New Approach for Aligning Parallel
Texts." Proceedings from the 15th International Conference on Computational
Linguistics, Kyoto.

Bigram Statistics Package by Ted Pedersen & Satanjeev Banerjee.
L<http://www.d.umn.edu/~tpederse/code.html>

=cut
