#!/usr/bin/perl
# 以下は変更する必要なし
#-----------------------------------------------------------------------------
#
# hex2double(version  $Id: eodv,v 1.4 2007/05/22 02:22:33 Exp $) 
#
# hex32bit(テキスト表記)から、数値(倍精度double)に変換する
# 
# Usage:
# > hex2double.pl hoge.txt
#
# hoge.txtの中身
# b6 a6 ac 29 6b ca ea 3f => 0.837209302325582
# 00 00 00 00 80 A8 F8 40 
# 00 00 00 00 C0 18 F8 40 
# 00 00 00 00 00 70 F7 40 
# 00 00 00 00 40 C7 F6 40 
# 00 00 00 00 C0 24 F6 40 
# 00 00 00 00 00 7C F5 40 
# 00 00 00 00 40 D3 F4 40 
# 00 00 00 00 00 82 F4 40 
# 
# options: none
#
# example:
# hex2double.pl hoge.txt				#(1)
#
#-----------------------------------------------------------------------------
# Libraries
#use strict;
#use warnings;

my $ver = "hex2double v1.0.0\n";
my $buf	= 0;
my $ch	= 0;
my $pint	= 0;
my $sint	= 0;
my $bnum	= 0;
my $flgc	= 0;
my $str1	= "_temp1.txt";
my $str2	= "_temp2.txt";
my $str3	= "_temp3.txt";
my $str4	= "_temp4.txt";
my $str5	= "_temp5.txt";
my $str6	= "_temp6.txt";
my $filename;
my @dat = ();

for(my $i=0;$i<256;$i++)
{
	for(my $j=0;$j<256;$j++)
  	{
  		$dat[$i][$j] = -1;
  	}
}

sub double_from_hex { unpack 'd', scalar reverse pack 'H*', $_[0] }

use constant POS_INF => double_from_hex '7FF0000000000000';
use constant NEG_INF => double_from_hex 'FFF0000000000000';
use constant NaN     => double_from_hex '7FF8000000000000';

#-----------------------------------------------------------------------------
# Code begin
#-----------------------------------------------------------------------------
# オプションがない場合
if ($#ARGV == -1)
{
	print $ver;
	print "Error:ファイル名を指定してください\n";
}
# オプションが1つある場合
if ($#ARGV == 0)
{
	print $ver;
	print "Now Loading...\n";
	
	## 1.元ファイルを読み込みテキスト変換を行う
	##------------------------------------------------------------------------
  	
  	## 3.HEXを読み込みヘッダ改行にする
  	##------------------------------------------------------------------------
  	open IN ,"<$ARGV[0]" or die "file open error : $ARGV[0]";
  	my @line = <IN>;
  	close IN;
  	
  	# ファイル名生成
  	$filename = (split(/\./,$ARGV[0]))[0];
  	$filename = $filename."_d.txt";
	open OUT,">$filename" or die "file open error : $filename";
  	
  	foreach(@line)
  	{
  		my $disp = $_;
  		
  		chomp($disp);
  		#$disp =~ s/\r\n//g;
  		
  		#my ($bottom, $top) = pack "L", hex($disp);
		#$d_val = unpack "d", pack "L", hex($disp);
		#print $disp;
		#my @nums = (
		#'b6 a6 ac 29 6b ca ea 3f',
		#'d0 06 d8 4a 48 37 eb 3f',
		#'d8 a5 51 20 82 63 e7 bf',
		#'10 44 70 ec d2 28 c0 3f',
		#'00 00 00 00 00 00 f0 7f',
		#);
		
		$i = 0;
		#for (@nums)
		#{
			#print $_,"<=>",$nums[$i],"\n";
			my @bytes = map {chr (hex ($_))} split / /;
		    #my @bytes = map {chr (hex ($_))} split / /;
		    #my @bytes = map {chr (hex ($nums[$i]))} split / /;
		    my $bytes = join '', @bytes;
		    $d_val = parse_double ($bytes);
		    #print ">",$bytes," ",parse_double ($bytes),  "\n";
		    
		    $i++;
		#}
		#my @bytes = map {chr (hex $nums[0])} split / /;
    	#my $bytes = join '', @bytes;
    	
		#$d_val = parse_double($bytes);
		
		print OUT $disp.",".$d_val."\n";
		
		#exit;
  	}

	close OUT;
	
	print "\n";
	print "Generating ...".$filename."\n";
	
  	## X.tempファイル削除
  	##------------------------------------------------------------------------
  	unlink($str1);  	
  	#unlink($str2);
  	#unlink($str3);
  	#unlink($str4);
  	#unlink($str5);
  	#unlink($str6); 	
}

# オプションが２つある場合
if ($#ARGV == 1){	
}
exit;

#-----------------------------------------------------------------------------
# Sub code begin
#-----------------------------------------------------------------------------
sub show_usage()
{
 print "Usage:\n";
 print "> RawHk2dssline.pl [-h]\n";
 print "\n";
 print "options:\n";
 print "         -h : 利用方法を提示する\n";
 print "\n";
 print "example:\n";
 print "RawHk2dssline.pl -h                         #(1) HELP\n";
}

sub parse_double
{
    my ($bytes) = @_;
    my ($bottom, $top) = unpack ("LL", $bytes);
    # Reference:
    # http://en.wikipedia.org/wiki/Double_precision_floating-point_format

    # Eight zero bytes represents 0.0.
    if ($bottom == 0) {
        if ($top == 0) {
            return 0;
        }
        elsif ($top == 0x80000000) {
            return -0;
        }
        elsif ($top == 0x7ff00000) {
            return POS_INF;
        }
        elsif ($top == 0xfff00000) {
            return NEG_INF;
        }
    }
    elsif ($top == 0x7ff00000) {
        return NaN;
    }
    my $sign = $top >> 31;
#    print "$sign\n";
    my $exponent = (($top >> 20) & 0x7FF) - 1023;
#    print "$exponent\n";
    my $e = ($top >> 20) & 0x7FF;
    my $t = $top & 0xFFFFF;
#    printf ("--> !%011b%020b \n--> %032b\n", $e, $t, $top);
    my $mantissa = ($bottom + ($t*(2**32))) / 2**52 + 1;
#    print "$mantissa\n";
    my $double = (-1)**$sign * 2**$exponent * $mantissa;
    
    return $double;
}

