* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
	 This file is a part of mp3packer . 

	 mp3packer 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 2 of the License , or 
	 ( at your option ) any later version . 

	 mp3packer 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  ; if not , write to the Free Software 
	 Foundation , Inc. , 51 Franklin St , Fifth Floor , Boston , MA   02110 - 1301   USA 
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	This file is a part of mp3packer.

	mp3packer 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 2 of the License, or
	(at your option) any later version.

	mp3packer 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 mp3packer; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*******************************************************************************)

  Huffman tables !

open Types;;
open Pack;;

(* get_huffman ht_num int_for_processing start_left_shift *)
external get_huffman_c : int -> int -> int -> int = "mfh_get_huffman" "noalloc";;
let get_huffman_big num i shift = get_huffman_c num i shift;;
let get_huffman_part1 num i shift = get_huffman_c (num + 32) i shift;;


external decode_big_quants_unsafe : Ptr.t -> int -> int -> Ptr.t -> int -> int -> int -> int * int = "mfh_decode_big_quants_bytecode" "mfh_decode_big_quants";;
let decode_big_quants in_ptr in_bit_off in_bit_off_to out_ptr out_quant_off out_quant_off_to ht decoder_error_ref =
	if in_bit_off < 0 || out_quant_off < 0 || ht < 0 || ht >= 32 then (
		invalid_arg "Mp3framehuffman.decode_big_quants";
	);
	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in
	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in
	decode_big_quants_unsafe in_ptr in_bit_off use_bit_off_to out_ptr out_quant_off use_quant_off_to ht
;;

external decode_all_big_quants_unsafe : Ptr.t -> int -> Ptr.t -> int -> int -> int -> int -> int -> int -> int -> int * int = "mfh_decode_all_big_quants_bytecode" "mfh_decode_all_big_quants";;
let decode_all_big_quants in_ptr in_bit_off out_ptr in_bit_off_to count0 ht0 count1 ht1 count2 ht2 decoder_error_ref =
	(* NOTE: count* values are actually the number of quants, NOT the number of quant pairs *)
	if in_bit_off < 0 || ht0 < 0 || ht0 >= 32 || ht1 < 0 || ht1 >= 32 || ht2 < 0 || ht2 >= 32 then (
		invalid_arg "Mp3framehuffman.decode_all_big_quants"
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in

	let use_count0 = if count0 * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		count0
	) in

	let use_count1 = if (use_count0 + count1) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0
	) else (
		count1
	) in

	let use_count2 = if (use_count0 + use_count1 + count2) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0 - use_count1
	) else (
		count2
	) in

	decode_all_big_quants_unsafe in_ptr in_bit_off out_ptr use_bit_off_to use_count0 ht0 use_count1 ht1 use_count2 ht2
;;

external decode_count1_quants_unsafe : Ptr.t -> int -> int -> Ptr.t -> int -> int -> bool -> bool * int * int = "mfh_decode_count1_quants_bytecode" "mfh_decode_count1_quants";;
let decode_count1_quants in_ptr in_bit_off in_bit_off_to out_ptr out_quant_off out_quant_off_to ht1 decoder_error_ref =
	if in_bit_off < 0 || out_quant_off < 0 then (
		invalid_arg "Mp3framehuffman.decode_count1_quants";
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in
	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in
	let ret = decode_count1_quants_unsafe in_ptr in_bit_off use_bit_off_to out_ptr out_quant_off use_quant_off_to ht1 in
	let (_, _, new_index) = ret in
	if new_index > out_quant_off_to then (
		decoder_error_ref := true;
	);
	ret
;;

external decode_all_quants_unsafe : Ptr.t -> int -> Ptr.t -> int -> int -> int -> int -> int -> int -> int -> int -> bool -> bool * bool * int * int = "mfh_decode_all_quants_bytecode" "mfh_decode_all_quants";;
let decode_all_quants in_ptr in_bit_off out_ptr in_bit_off_to count0 ht0 count1 ht1 count2 ht2 out_quant_off_to ht1_table1 decoder_error_ref =
	if in_bit_off < 0 || ht0 < 0 || ht0 >= 32 || ht1 < 0 || ht1 >= 32 || ht2 < 0 || ht2 >= 32 then (
		invalid_arg "Mp3framehuffman.decode_all_quants"
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in

	let use_count0 = if count0 * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		count0
	) in

	let use_count1 = if (use_count0 + count1) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0
	) else (
		count1
	) in

	let use_count2 = if (use_count0 + use_count1 + count2) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0 - use_count1
	) else (
		count2
	) in

	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in

	let ret = decode_all_quants_unsafe in_ptr in_bit_off out_ptr use_bit_off_to use_count0 ht0 use_count1 ht1 use_count2 ht2 use_quant_off_to ht1_table1 in
	let (new_error, new_overboard, new_bit_off, new_index) = ret in
	if new_index > out_quant_off_to then (
		decoder_error_ref := true;
	);
	decoder_error_ref := !decoder_error_ref || new_error;
	(new_overboard, new_bit_off, new_index)
;;


let too_many_bits = 32768;;

let htX = [||];;

let ht0 = [|
	((0,0), 0, 0b0);
|];;

let ht1 = [|
	((0,0), 1, 0b1  );
	((0,1), 3, 0b001);
	((1,0), 2, 0b01 );
	((1,1), 3, 0b000);
|];;

let ht2 = [|
	((0,0), 1, 0b1     );
	((0,1), 3, 0b010   );
	((0,2), 6, 0b000001);
	((1,0), 3, 0b011   );
	((1,1), 3, 0b001   );
	((1,2), 5, 0b00001 );
	((2,0), 5, 0b00011 );
	((2,1), 5, 0b00010 );
	((2,2), 6, 0b000000);
|];;

let ht3 = [|
	((0,0), 2, 0b11    );
	((0,1), 2, 0b10    );
	((0,2), 6, 0b000001);
	((1,0), 3, 0b001   );
	((1,1), 2, 0b01    );
	((1,2), 5, 0b00001 );
	((2,0), 5, 0b00011 );
	((2,1), 5, 0b00010 );
	((2,2), 6, 0b000000);
|];;

(* For some reason, ht4 doesn't exist... *)

let ht5 = [|
	((0,0), 1, 0b1       );
	((0,1), 3, 0b010     );
	((0,2), 6, 0b000110  );
	((0,3), 7, 0b0000101 );
	((1,0), 3, 0b011     );
	((1,1), 3, 0b001     );
	((1,2), 6, 0b000100  );
	((1,3), 7, 0b0000100 );
	((2,0), 6, 0b000111  );
	((2,1), 6, 0b000101  );
	((2,2), 7, 0b0000111 );
	((2,3), 8, 0b00000001);
	((3,0), 7, 0b0000110 );
	((3,1), 6, 0b000001  );
	((3,2), 7, 0b0000001 );
	((3,3), 8, 0b00000000);
|];;

let ht6 = [|
	((0,0), 3, 0b111    );
	((0,1), 3, 0b011    );
	((0,2), 5, 0b00101  );
	((0,3), 7, 0b0000001);
	((1,0), 3, 0b110    );
	((1,1), 2, 0b10     );
	((1,2), 4, 0b0011   );
	((1,3), 5, 0b00010  );
	((2,0), 4, 0b0101   );
	((2,1), 4, 0b0100   );
	((2,2), 5, 0b00100  );
	((2,3), 6, 0b000001 );
	((3,0), 6, 0b000011 );
	((3,1), 5, 0b00011  );
	((3,2), 6, 0b000010 );
	((3,3), 7, 0b0000000);
|];;

let ht7 = [|
	((0,0), 1 , 0b1         );
	((0,1), 3 , 0b010       );
	((0,2), 6 , 0b001010    );
	((0,3), 8 , 0b00010011  );
	((0,4), 8 , 0b00010000  );
	((0,5), 9 , 0b000001010 );
	((1,0), 3 , 0b011       );
	((1,1), 4 , 0b0011      );
	((1,2), 6 , 0b000111    );
	((1,3), 7 , 0b0001010   );
	((1,4), 7 , 0b0000101   );
	((1,5), 8 , 0b00000011  );
	((2,0), 6 , 0b001011    );
	((2,1), 5 , 0b00100     );
	((2,2), 7 , 0b0001101   );
	((2,3), 8 , 0b00010001  );
	((2,4), 8 , 0b00001000  );
	((2,5), 9 , 0b000000100 );
	((3,0), 7 , 0b0001100   );
	((3,1), 7 , 0b0001011   );
	((3,2), 8 , 0b00010010  );
	((3,3), 9 , 0b000001111 );
	((3,4), 9 , 0b000001011 );
	((3,5), 9 , 0b000000010 );
	((4,0), 7 , 0b0000111   );
	((4,1), 7 , 0b0000110   );
	((4,2), 8 , 0b00001001  );
	((4,3), 9 , 0b000001110 );
	((4,4), 9 , 0b000000011 );
	((4,5), 10, 0b0000000001);
	((5,0), 8 , 0b00000110  );
	((5,1), 8 , 0b00000100  );
	((5,2), 9 , 0b000000101 );
	((5,3), 10, 0b0000000011);
	((5,4), 10, 0b0000000010);
	((5,5), 10, 0b0000000000);
|];;

let ht8 = [|
	((0,0), 2 , 0b11         );
	((0,1), 3 , 0b100        );
	((0,2), 6 , 0b000110     );
	((0,3), 8 , 0b00010010   );
	((0,4), 8 , 0b00001100   );
	((0,5), 9 , 0b000000101  );
	((1,0), 3 , 0b101        );
	((1,1), 2 , 0b01         );
	((1,2), 4 , 0b0010       );
	((1,3), 8 , 0b00010000   );
	((1,4), 8 , 0b00001001   );
	((1,5), 8 , 0b00000011   );
	((2,0), 6 , 0b000111     );
	((2,1), 4 , 0b0011       );
	((2,2), 6 , 0b000101     );
	((2,3), 8 , 0b00001110   );
	((2,4), 8 , 0b00000111   );
	((2,5), 9 , 0b000000011  );
	((3,0), 8 , 0b00010011   );
	((3,1), 8 , 0b00010001   );
	((3,2), 8 , 0b00001111   );
	((3,3), 9 , 0b000001101  );
	((3,4), 9 , 0b000001010  );
	((3,5), 10, 0b0000000100 );
	((4,0), 8 , 0b00001101   );
	((4,1), 7 , 0b0000101    );
	((4,2), 8 , 0b00001000   );
	((4,3), 9 , 0b000001011  );
	((4,4), 10, 0b0000000101 );
	((4,5), 10, 0b0000000001 );
	((5,0), 9 , 0b000001100  );
	((5,1), 8 , 0b00000100   );
	((5,2), 9 , 0b000000100  );
	((5,3), 9 , 0b000000001  );
	((5,4), 11, 0b00000000001);
	((5,5), 11, 0b00000000000);
|];;

let ht9 = [|
	((0,0), 3, 0b111      );
	((0,1), 3, 0b101      );
	((0,2), 5, 0b01001    );
	((0,3), 6, 0b001110   );
	((0,4), 8, 0b00001111 );
	((0,5), 9, 0b000000111);
	((1,0), 3, 0b110      );
	((1,1), 3, 0b100      );
	((1,2), 4, 0b0101     );
	((1,3), 5, 0b00101    );
	((1,4), 6, 0b000110   );
	((1,5), 8, 0b00000111 );
	((2,0), 4, 0b0111     );
	((2,1), 4, 0b0110     );
	((2,2), 5, 0b01000    );
	((2,3), 6, 0b001000   );
	((2,4), 7, 0b0001000  );
	((2,5), 8, 0b00000101 );
	((3,0), 6, 0b001111   );
	((3,1), 5, 0b00110    );
	((3,2), 6, 0b001001   );
	((3,3), 7, 0b0001010  );
	((3,4), 7, 0b0000101  );
	((3,5), 8, 0b00000001 );
	((4,0), 7, 0b0001011  );
	((4,1), 6, 0b000111   );
	((4,2), 7, 0b0001001  );
	((4,3), 7, 0b0000110  );
	((4,4), 8, 0b00000100 );
	((4,5), 9, 0b000000001);
	((5,0), 8, 0b00001110 );
	((5,1), 7, 0b0000100  );
	((5,2), 8, 0b00000110 );
	((5,3), 8, 0b00000010 );
	((5,4), 9, 0b000000110);
	((5,5), 9, 0b000000000);
|];;

let ht10 = [|
	((0,0),1 , 0b1          );
	((0,1),3 , 0b010        );
	((0,2),6 , 0b001010     );
	((0,3),8 , 0b00010111   );
	((0,4),9 , 0b000100011  );
	((0,5),9 , 0b000011110  );
	((0,6),9 , 0b000001100  );
	((0,7),10, 0b0000010001 );
	((1,0),3 , 0b011        );
	((1,1),4 , 0b0011       );
	((1,2),6 , 0b001000     );
	((1,3),7 , 0b0001100    );
	((1,4),8 , 0b00010010   );
	((1,5),9 , 0b000010101  );
	((1,6),8 , 0b00001100   );
	((1,7),8 , 0b00000111   );
	((2,0),6 , 0b001011     );
	((2,1),6 , 0b001001     );
	((2,2),7 , 0b0001111    );
	((2,3),8 , 0b00010101   );
	((2,4),9 , 0b000100000  );
	((2,5),10, 0b0000101000 );
	((2,6),9 , 0b000010011  );
	((2,7),9 , 0b000000110  );
	((3,0),7 , 0b0001110    );
	((3,1),7 , 0b0001101    );
	((3,2),8 , 0b00010110   );
	((3,3),9 , 0b000100010  );
	((3,4),10, 0b0000101110 );
	((3,5),10, 0b0000010111 );
	((3,6),9 , 0b000010010  );
	((3,7),10, 0b0000000111 );
	((4,0),8 , 0b00010100   );
	((4,1),8 , 0b00010011   );
	((4,2),9 , 0b000100001  );
	((4,3),10, 0b0000101111 );
	((4,4),10, 0b0000011011 );
	((4,5),10, 0b0000010110 );
	((4,6),10, 0b0000001001 );
	((4,7),10, 0b0000000011 );
	((5,0),9 , 0b000011111  );
	((5,1),9 , 0b000010110  );
	((5,2),10, 0b0000101001 );
	((5,3),10, 0b0000011010 );
	((5,4),11, 0b00000010101);
	((5,5),11, 0b00000010100);
	((5,6),10, 0b0000000101 );
	((5,7),11, 0b00000000011);
	((6,0),8 , 0b00001110   );
	((6,1),8 , 0b00001101   );
	((6,2),9 , 0b000001010  );
	((6,3),10, 0b0000001011 );
	((6,4),10, 0b0000010000 );
	((6,5),10, 0b0000000110 );
	((6,6),11, 0b00000000101);
	((6,7),11, 0b00000000001);
	((7,0),9 , 0b000001001  );
	((7,1),8 , 0b00001000   );
	((7,2),9 , 0b000000111  );
	((7,3),10, 0b0000001000 );
	((7,4),10, 0b0000000100 );
	((7,5),11, 0b00000000100);
	((7,6),11, 0b00000000010);
	((7,7),11, 0b00000000000);
|];;

let ht11 = [|
	((0,0), 2 , 0b11         );
	((0,1), 3 , 0b100        );
	((0,2), 5 , 0b01010      );
	((0,3), 7 , 0b0011000    );
	((0,4), 8 , 0b00100010   );
	((0,5), 9 , 0b000100001  );
	((0,6), 8 , 0b00010101   );
	((0,7), 9 , 0b000001111  );
	((1,0), 3 , 0b101        );
	((1,1), 3 , 0b011        );
	((1,2), 4 , 0b0100       );
	((1,3), 6 , 0b001010     );
	((1,4), 8 , 0b00100000   );
	((1,5), 8 , 0b00010001   );
	((1,6), 7 , 0b0001011    );
	((1,7), 8 , 0b00001010   );
	((2,0), 5 , 0b01011      );
	((2,1), 5 , 0b00111      );
	((2,2), 6 , 0b001101     );
	((2,3), 7 , 0b0010010    );
	((2,4), 8 , 0b00011110   );
	((2,5), 9 , 0b000011111  );
	((2,6), 8 , 0b00010100   );
	((2,7), 8 , 0b00000101   );
	((3,0), 7 , 0b0011001    );
	((3,1), 6 , 0b001011     );
	((3,2), 7 , 0b0010011    );
	((3,3), 9 , 0b000111011  );
	((3,4), 8 , 0b00011011   );
	((3,5), 10, 0b0000010010 );
	((3,6), 8 , 0b00001100   );
	((3,7), 9 , 0b000000101  );
	((4,0), 8 , 0b00100011   );
	((4,1), 8 , 0b00100001   );
	((4,2), 8 , 0b00011111   );
	((4,3), 9 , 0b000111010  );
	((4,4), 9 , 0b000011110  );
	((4,5), 10, 0b0000010000 );
	((4,6), 9 , 0b000000111  );
	((4,7), 10, 0b0000000101 );
	((5,0), 8 , 0b00011100   );
	((5,1), 8 , 0b00011010   );
	((5,2), 9 , 0b000100000  );
	((5,3), 10, 0b0000010011 );
	((5,4), 10, 0b0000010001 );
	((5,5), 11, 0b00000001111);
	((5,6), 10, 0b0000001000 );
	((5,7), 11, 0b00000001110);
	((6,0), 8 , 0b00001110   );
	((6,1), 7 , 0b0001100    );
	((6,2), 7 , 0b0001001    );
	((6,3), 8 , 0b00001101   );
	((6,4), 9 , 0b000001110  );
	((6,5), 10, 0b0000001001 );
	((6,6), 10, 0b0000000100 );
	((6,7), 10, 0b0000000001 );
	((7,0), 8 , 0b00001011   );
	((7,1), 7 , 0b0000100    );
	((7,2), 8 , 0b00000110   );
	((7,3), 9 , 0b000000110  );
	((7,4), 10, 0b0000000110 );
	((7,5), 10, 0b0000000011 );
	((7,6), 10, 0b0000000010 );
	((7,7), 10, 0b0000000000 );
|];;

let ht12 = [|
	((0,0),4 , 0b1001      );
	((0,1),3 , 0b110       );
	((0,2),5 , 0b10000     );
	((0,3),7 , 0b0100001   );
	((0,4),8 , 0b00101001  );
	((0,5),9 , 0b000100111 );
	((0,6),9 , 0b000100110 );
	((0,7),9 , 0b000011010 );
	((1,0),3 , 0b111       );
	((1,1),3 , 0b101       );
	((1,2),4 , 0b0110      );
	((1,3),5 , 0b01001     );
	((1,4),7 , 0b0010111   );
	((1,5),7 , 0b0010000   );
	((1,6),8 , 0b00011010  );
	((1,7),8 , 0b00001011  );
	((2,0),5 , 0b10001     );
	((2,1),4 , 0b0111      );
	((2,2),5 , 0b01011     );
	((2,3),6 , 0b001110    );
	((2,4),7 , 0b0010101   );
	((2,5),8 , 0b00011110  );
	((2,6),7 , 0b0001010   );
	((2,7),8 , 0b00000111  );
	((3,0),6 , 0b010001    );
	((3,1),5 , 0b01010     );
	((3,2),6 , 0b001111    );
	((3,3),6 , 0b001100    );
	((3,4),7 , 0b0010010   );
	((3,5),8 , 0b00011100  );
	((3,6),8 , 0b00001110  );
	((3,7),8 , 0b00000101  );
	((4,0),7 , 0b0100000   );
	((4,1),6 , 0b001101    );
	((4,2),7 , 0b0010110   );
	((4,3),7 , 0b0010011   );
	((4,4),8 , 0b00010010  );
	((4,5),8 , 0b00010000  );
	((4,6),8 , 0b00001001  );
	((4,7),9 , 0b000000101 );
	((5,0),8 , 0b00101000  );
	((5,1),7 , 0b0010001   );
	((5,2),8 , 0b00011111  );
	((5,3),8 , 0b00011101  );
	((5,4),8 , 0b00010001  );
	((5,5),9 , 0b000001101 );
	((5,6),8 , 0b00000100  );
	((5,7),9 , 0b000000010 );
	((6,0),8 , 0b00011011  );
	((6,1),7 , 0b0001100   );
	((6,2),7 , 0b0001011   );
	((6,3),8 , 0b00001111  );
	((6,4),8 , 0b00001010  );
	((6,5),9 , 0b000000111 );
	((6,6),9 , 0b000000100 );
	((6,7),10, 0b0000000001);
	((7,0),9 , 0b000011011 );
	((7,1),8 , 0b00001100  );
	((7,2),8 , 0b00001000  );
	((7,3),9 , 0b000001100 );
	((7,4),9 , 0b000000110 );
	((7,5),9 , 0b000000011 );
	((7,6),9 , 0b000000001 );
	((7,7),10, 0b0000000000);
|];;

let ht13 = [|
	(( 0,0 ), 1 , 0b1                  );
	(( 0,1 ), 4 , 0b0101               );
	(( 0,2 ), 6 , 0b001110             );
	(( 0,3 ), 7 , 0b0010101            );
	(( 0,4 ), 8 , 0b00100010           );
	(( 0,5 ), 9 , 0b000110011          );
	(( 0,6 ), 9 , 0b000101110          );
	(( 0,7 ), 10, 0b0001000111         );
	(( 0,8 ), 9 , 0b000101010          );
	(( 0,9 ), 10, 0b0000110100         );
	(( 0,10), 11, 0b00001000100        );
	(( 0,11), 11, 0b00000110100        );
	(( 0,12), 12, 0b000001000011       );
	(( 0,13), 12, 0b000000101100       );
	(( 0,14), 13, 0b0000000101011      );
	(( 0,15), 13, 0b0000000010011      );
	(( 1,0 ), 3 , 0b011                );
	(( 1,1 ), 4 , 0b0100               );
	(( 1,2 ), 6 , 0b001100             );
	(( 1,3 ), 7 , 0b0010011            );
	(( 1,4 ), 8 , 0b00011111           );
	(( 1,5 ), 8 , 0b00011010           );
	(( 1,6 ), 9 , 0b000101100          );
	(( 1,7 ), 9 , 0b000100001          );
	(( 1,8 ), 9 , 0b000011111          );
	(( 1,9 ), 9 , 0b000011000          );
	(( 1,10), 10, 0b0000100000         );
	(( 1,11), 10, 0b0000011000         );
	(( 1,12), 11, 0b00000011111        );
	(( 1,13), 12, 0b000000100011       );
	(( 1,14), 12, 0b000000010110       );
	(( 1,15), 12, 0b000000001110       );
	(( 2,0 ), 6 , 0b001111             );
	(( 2,1 ), 6 , 0b001101             );
	(( 2,2 ), 7 , 0b0010111            );
	(( 2,3 ), 8 , 0b00100100           );
	(( 2,4 ), 9 , 0b000111011          );
	(( 2,5 ), 9 , 0b000110001          );
	(( 2,6 ), 10, 0b0001001101         );
	(( 2,7 ), 10, 0b0001000001         );
	(( 2,8 ), 9 , 0b000011101          );
	(( 2,9 ), 10, 0b0000101000         );
	(( 2,10), 10, 0b0000011110         );
	(( 2,11), 11, 0b00000101000        );
	(( 2,12), 11, 0b00000011011        );
	(( 2,13), 12, 0b000000100001       );
	(( 2,14), 13, 0b0000000101010      );
	(( 2,15), 13, 0b0000000010000      );
	(( 3,0 ), 7 , 0b0010110            );
	(( 3,1 ), 7 , 0b0010100            );
	(( 3,2 ), 8 , 0b00100101           );
	(( 3,3 ), 9 , 0b000111101          );
	(( 3,4 ), 9 , 0b000111000          );
	(( 3,5 ), 10, 0b0001001111         );
	(( 3,6 ), 10, 0b0001001001         );
	(( 3,7 ), 10, 0b0001000000         );
	(( 3,8 ), 10, 0b0000101011         );
	(( 3,9 ), 11, 0b00001001100        );
	(( 3,10), 11, 0b00000111000        );
	(( 3,11), 11, 0b00000100101        );
	(( 3,12), 11, 0b00000011010        );
	(( 3,13), 12, 0b000000011111       );
	(( 3,14), 13, 0b0000000011001      );
	(( 3,15), 13, 0b0000000001110      );
	(( 4,0 ), 8 , 0b00100011           );
	(( 4,1 ), 7 , 0b0010000            );
	(( 4,2 ), 9 , 0b000111100          );
	(( 4,3 ), 9 , 0b000111001          );
	(( 4,4 ), 10, 0b0001100001         );
	(( 4,5 ), 10, 0b0001001011         );
	(( 4,6 ), 11, 0b00001110010        );
	(( 4,7 ), 11, 0b00001011011        );
	(( 4,8 ), 10, 0b0000110110         );
	(( 4,9 ), 11, 0b00001001001        );
	(( 4,10), 11, 0b00000110111        );
	(( 4,11), 12, 0b000000101001       );
	(( 4,12), 12, 0b000000110000       );
	(( 4,13), 13, 0b0000000110101      );
	(( 4,14), 13, 0b0000000010111      );
	(( 4,15), 14, 0b00000000011000     );
	(( 5,0 ), 9 , 0b000111010          );
	(( 5,1 ), 8 , 0b00011011           );
	(( 5,2 ), 9 , 0b000110010          );
	(( 5,3 ), 10, 0b0001100000         );
	(( 5,4 ), 10, 0b0001001100         );
	(( 5,5 ), 10, 0b0001000110         );
	(( 5,6 ), 11, 0b00001011101        );
	(( 5,7 ), 11, 0b00001010100        );
	(( 5,8 ), 11, 0b00001001101        );
	(( 5,9 ), 11, 0b00000111010        );
	(( 5,10), 12, 0b000001001111       );
	(( 5,11), 11, 0b00000011101        );
	(( 5,12), 13, 0b0000001001010      );
	(( 5,13), 13, 0b0000000110001      );
	(( 5,14), 14, 0b00000000101001     );
	(( 5,15), 14, 0b00000000010001     );
	(( 6,0 ), 9 , 0b000101111          );
	(( 6,1 ), 9 , 0b000101101          );
	(( 6,2 ), 10, 0b0001001110         );
	(( 6,3 ), 10, 0b0001001010         );
	(( 6,4 ), 11, 0b00001110011        );
	(( 6,5 ), 11, 0b00001011110        );
	(( 6,6 ), 11, 0b00001011010        );
	(( 6,7 ), 11, 0b00001001111        );
	(( 6,8 ), 11, 0b00001000101        );
	(( 6,9 ), 12, 0b000001010011       );
	(( 6,10), 12, 0b000001000111       );
	(( 6,11), 12, 0b000000110010       );
	(( 6,12), 13, 0b0000000111011      );
	(( 6,13), 13, 0b0000000100110      );
	(( 6,14), 14, 0b00000000100100     );
	(( 6,15), 14, 0b00000000001111     );
	(( 7,0 ), 10, 0b0001001000         );
	(( 7,1 ), 9 , 0b000100010          );
	(( 7,2 ), 10, 0b0000111000         );
	(( 7,3 ), 11, 0b00001011111        );
	(( 7,4 ), 11, 0b00001011100        );
	(( 7,5 ), 11, 0b00001010101        );
	(( 7,6 ), 12, 0b000001011011       );
	(( 7,7 ), 12, 0b000001011010       );
	(( 7,8 ), 12, 0b000001010110       );
	(( 7,9 ), 12, 0b000001001001       );
	(( 7,10), 13, 0b0000001001101      );
	(( 7,11), 13, 0b0000001000001      );
	(( 7,12), 13, 0b0000000110011      );
	(( 7,13), 14, 0b00000000101100     );
	(( 7,14), 16, 0b0000000000101011   );
	(( 7,15), 16, 0b0000000000101010   );
	(( 8,0 ), 9 , 0b000101011          );
	(( 8,1 ), 8 , 0b00010100           );
	(( 8,2 ), 9 , 0b000011110          );
	(( 8,3 ), 10, 0b0000101100         );
	(( 8,4 ), 10, 0b0000110111         );
	(( 8,5 ), 11, 0b00001001110        );
	(( 8,6 ), 11, 0b00001001000        );
	(( 8,7 ), 12, 0b000001010111       );
	(( 8,8 ), 12, 0b000001001110       );
	(( 8,9 ), 12, 0b000000111101       );
	(( 8,10), 12, 0b000000101110       );
	(( 8,11), 13, 0b0000000110110      );
	(( 8,12), 13, 0b0000000100101      );
	(( 8,13), 14, 0b00000000011110     );
	(( 8,14), 15, 0b000000000010100    );
	(( 8,15), 15, 0b000000000010000    );
	(( 9,0 ), 10, 0b0000110101         );
	(( 9,1 ), 9 , 0b000011001          );
	(( 9,2 ), 10, 0b0000101001         );
	(( 9,3 ), 10, 0b0000100101         );
	(( 9,4 ), 11, 0b00000101100        );
	(( 9,5 ), 11, 0b00000111011        );
	(( 9,6 ), 11, 0b00000110110        );
	(( 9,7 ), 13, 0b0000001010001      );
	(( 9,8 ), 12, 0b000001000010       );
	(( 9,9 ), 13, 0b0000001001100      );
	(( 9,10), 13, 0b0000000111001      );
	(( 9,11), 14, 0b00000000110110     );
	(( 9,12), 14, 0b00000000100101     );
	(( 9,13), 14, 0b00000000010010     );
	(( 9,14), 16, 0b0000000000100111   );
	(( 9,15), 15, 0b000000000001011    );
	((10,0 ), 10, 0b0000100011         );
	((10,1 ), 10, 0b0000100001         );
	((10,2 ), 10, 0b0000011111         );
	((10,3 ), 11, 0b00000111001        );
	((10,4 ), 11, 0b00000101010        );
	((10,5 ), 12, 0b000001010010       );
	((10,6 ), 12, 0b000001001000       );
	((10,7 ), 13, 0b0000001010000      );
	((10,8 ), 12, 0b000000101111       );
	((10,9 ), 13, 0b0000000111010      );
	((10,10), 14, 0b00000000110111     );
	((10,11), 13, 0b0000000010101      );
	((10,12), 14, 0b00000000010110     );
	((10,13), 15, 0b000000000011010    );
	((10,14), 16, 0b0000000000100110   );
	((10,15), 17, 0b00000000000010110  );
	((11,0 ), 11, 0b00000110101        );
	((11,1 ), 10, 0b0000011001         );
	((11,2 ), 10, 0b0000010111         );
	((11,3 ), 11, 0b00000100110        );
	((11,4 ), 12, 0b000001000110       );
	((11,5 ), 12, 0b000000111100       );
	((11,6 ), 12, 0b000000110011       );
	((11,7 ), 12, 0b000000100100       );
	((11,8 ), 13, 0b0000000110111      );
	((11,9 ), 13, 0b0000000011010      );
	((11,10), 13, 0b0000000100010      );
	((11,11), 14, 0b00000000010111     );
	((11,12), 15, 0b000000000011011    );
	((11,13), 15, 0b000000000001110    );
	((11,14), 15, 0b000000000001001    );
	((11,15), 16, 0b0000000000000111   );
	((12,0 ), 11, 0b00000100010        );
	((12,1 ), 11, 0b00000100000        );
	((12,2 ), 11, 0b00000011100        );
	((12,3 ), 12, 0b000000100111       );
	((12,4 ), 12, 0b000000110001       );
	((12,5 ), 13, 0b0000001001011      );
	((12,6 ), 12, 0b000000011110       );
	((12,7 ), 13, 0b0000000110100      );
	((12,8 ), 14, 0b00000000110000     );
	((12,9 ), 14, 0b00000000101000     );
	((12,10), 15, 0b000000000110100    );
	((12,11), 15, 0b000000000011100    );
	((12,12), 15, 0b000000000010010    );
	((12,13), 16, 0b0000000000010001   );
	((12,14), 16, 0b0000000000001001   );
	((12,15), 16, 0b0000000000000101   );
	((13,0 ), 12, 0b000000101101       );
	((13,1 ), 11, 0b00000010101        );
	((13,2 ), 12, 0b000000100010       );
	((13,3 ), 13, 0b0000001000000      );
	((13,4 ), 13, 0b0000000111000      );
	((13,5 ), 13, 0b0000000110010      );
	((13,6 ), 14, 0b00000000110001     );
	((13,7 ), 14, 0b00000000101101     );
	((13,8 ), 14, 0b00000000011111     );
	((13,9 ), 14, 0b00000000010011     );
	((13,10), 14, 0b00000000001100     );
	((13,11), 15, 0b000000000001111    );
	((13,12), 16, 0b0000000000001010   );
	((13,13), 15, 0b000000000000111    );
	((13,14), 16, 0b0000000000000110   );
	((13,15), 16, 0b0000000000000011   );
	((14, 0), 13, 0b0000000110000      );
	((14, 1), 12, 0b000000010111       );
	((14, 2), 12, 0b000000010100       );
	((14, 3), 13, 0b0000000100111      );
	((14, 4), 13, 0b0000000100100      );
	((14, 5), 13, 0b0000000100011      );
	((14, 6), 15, 0b000000000110101    );
	((14, 7), 14, 0b00000000010101     );
	((14, 8), 14, 0b00000000010000     );
	((14, 9), 17, 0b00000000000010111  );
	((14,10), 15, 0b000000000001101    );
	((14,11), 15, 0b000000000001010    );
	((14,12), 15, 0b000000000000110    );
	((14,13), 17, 0b00000000000000001  );
	((14,14), 16, 0b0000000000000100   );
	((14,15), 16, 0b0000000000000010   );
	((15, 0), 12, 0b000000010000       );
	((15, 1), 12, 0b000000001111       );
	((15, 2), 13, 0b0000000010001      );
	((15, 3), 14, 0b00000000011011     );
	((15, 4), 14, 0b00000000011001     );
	((15, 5), 14, 0b00000000010100     );
	((15, 6), 15, 0b000000000011101    );
	((15, 7), 14, 0b00000000001011     );
	((15, 8), 15, 0b000000000010001    );
	((15, 9), 15, 0b000000000001100    );
	((15,10), 16, 0b0000000000010000   );
	((15,11), 16, 0b0000000000001000   );
	((15,12), 19, 0b0000000000000000001);
	((15,13), 18, 0b000000000000000001 );
	((15,14), 19, 0b0000000000000000000);
	((15,15), 16, 0b0000000000000001   );
|];;

  No table 14 either ...

let   ht15   =   [|
	(( 0, 0),  3, 0b111          );
	(( 0, 1),  4, 0b1100         );
	(( 0, 2),  5, 0b10010        );
	(( 0, 3),  7, 0b0110101      );
	(( 0, 4),  7, 0b0101111      );
	(( 0, 5),  8, 0b01001100     );
	(( 0, 6),  9, 0b001111100    );
	(( 0, 7),  9, 0b001101100    );
	(( 0, 8),  9, 0b001011001    );
	(( 0, 9), 10, 0b0001111011   );
	(( 0,10), 10, 0b0001101100   );
	(( 0,11), 11, 0b00001110111  );
	(( 0,12), 11, 0b00001101011  );
	(( 0,13), 11, 0b00001010001  );
	(( 0,14), 12, 0b000001111010 );
	(( 0,15), 13, 0b0000000111111);
	(( 1, 0),  4, 0b1101         );
	(( 1, 1),  3, 0b101          );
	(( 1, 2),  5, 0b10000        );
	(( 1, 3),  6, 0b011011       );
	(( 1, 4),  7, 0b0101110      );
	(( 1, 5),  7, 0b0100100      );
	(( 1, 6),  8, 0b00111101     );
	(( 1, 7),  8, 0b00110011     );
	(( 1, 8),  8, 0b00101010     );
	(( 1, 9),  9, 0b001000110    );
	(( 1,10),  9, 0b000110100    );
	(( 1,11), 10, 0b0001010011   );
	(( 1,12), 10, 0b0001000001   );
	(( 1,13), 10, 0b0000101001   );
	(( 1,14), 11, 0b00000111011  );
	(( 1,15), 11, 0b00000100100  );
	(( 2, 0),  5, 0b10011        );
	(( 2, 1),  5, 0b10001        );
	(( 2, 2),  5, 0b01111        );
	(( 2, 3),  6, 0b011000       );
	(( 2, 4),  7, 0b0101001      );
	(( 2, 5),  7, 0b0100010      );
	(( 2, 6),  8, 0b00111011     );
	(( 2, 7),  8, 0b00110000     );
	(( 2, 8),  8, 0b00101000     );
	(( 2, 9),  9, 0b001000000    );
	(( 2,10),  9, 0b000110010    );
	(( 2,11), 10, 0b0001001110   );
	(( 2,12), 10, 0b0000111110   );
	(( 2,13), 11, 0b00001010000  );
	(( 2,14), 11, 0b00000111000  );
	(( 2,15), 11, 0b00000100001  );
	(( 3, 0),  6, 0b011101       );
	(( 3, 1),  6, 0b011100       );
	(( 3, 2),  6, 0b011001       );
	(( 3, 3),  7, 0b0101011      );
	(( 3, 4),  7, 0b0100111      );
	(( 3, 5),  8, 0b00111111     );
	(( 3, 6),  8, 0b00110111     );
	(( 3, 7),  9, 0b001011101    );
	(( 3, 8),  9, 0b001001100    );
	(( 3, 9),  9, 0b000111011    );
	(( 3,10), 10, 0b0001011101   );
	(( 3,11), 10, 0b0001001000   );
	(( 3,12), 10, 0b0000110110   );
	(( 3,13), 11, 0b00001001011  );
	(( 3,14), 11, 0b00000110010  );
	(( 3,15), 11, 0b00000011101  );
	(( 4, 0),  7, 0b0110100      );
	(( 4, 1),  6, 0b010110       );
	(( 4, 2),  7, 0b0101010      );
	(( 4, 3),  7, 0b0101000      );
	(( 4, 4),  8, 0b01000011     );
	(( 4, 5),  8, 0b00111001     );
	(( 4, 6),  9, 0b001011111    );
	(( 4, 7),  9, 0b001001111    );
	(( 4, 8),  9, 0b001001000    );
	(( 4, 9),  9, 0b000111001    );
	(( 4,10), 10, 0b0001011001   );
	(( 4,11), 10, 0b0001000101   );
	(( 4,12), 10, 0b0000110001   );
	(( 4,13), 11, 0b00001000010  );
	(( 4,14), 11, 0b00000101110  );
	(( 4,15), 11, 0b00000011011  );
	(( 5, 0),  8, 0b01001101     );
	(( 5, 1),  7, 0b0100101      );
	(( 5, 2),  7, 0b0100011      );
	(( 5, 3),  8, 0b01000010     );
	(( 5, 4),  8, 0b00111010     );
	(( 5, 5),  8, 0b00110100     );
	(( 5, 6),  9, 0b001011011    );
	(( 5, 7),  9, 0b001001010    );
	(( 5, 8),  9, 0b000111110    );
	(( 5, 9),  9, 0b000110000    );
	(( 5,10), 10, 0b0001001111   );
	(( 5,11), 10, 0b0000111111   );
	(( 5,12), 11, 0b00001011010  );
	(( 5,13), 11, 0b00000111110  );
	(( 5,14), 11, 0b00000101000  );
	(( 5,15), 12, 0b000000100110 );
	(( 6, 0),  9, 0b001111101    );
	(( 6, 1),  7, 0b0100000      );
	(( 6, 2),  8, 0b00111100     );
	(( 6, 3),  8, 0b00111000     );
	(( 6, 4),  8, 0b00110010     );
	(( 6, 5),  9, 0b001011100    );
	(( 6, 6),  9, 0b001001110    );
	(( 6, 7),  9, 0b001000001    );
	(( 6, 8),  9, 0b000110111    );
	(( 6, 9), 10, 0b0001010111   );
	(( 6,10), 10, 0b0001000111   );
	(( 6,11), 10, 0b0000110011   );
	(( 6,12), 11, 0b00001001001  );
	(( 6,13), 11, 0b00000110011  );
	(( 6,14), 12, 0b000001000110 );
	(( 6,15), 12, 0b000000011110 );
	(( 7, 0),  9, 0b001101101    );
	(( 7, 1),  8, 0b00110101     );
	(( 7, 2),  8, 0b00110001     );
	(( 7, 3),  9, 0b001011110    );
	(( 7, 4),  9, 0b001011000    );
	(( 7, 5),  9, 0b001001011    );
	(( 7, 6),  9, 0b001000010    );
	(( 7, 7), 10, 0b0001111010   );
	(( 7, 8), 10, 0b0001011011   );
	(( 7, 9), 10, 0b0001001001   );
	(( 7,10), 10, 0b0000111000   );
	(( 7,11), 10, 0b0000101010   );
	(( 7,12), 11, 0b00001000000  );
	(( 7,13), 11, 0b00000101100  );
	(( 7,14), 11, 0b00000010101  );
	(( 7,15), 12, 0b000000011001 );
	(( 8, 0),  9, 0b001011010    );
	(( 8, 1),  8, 0b00101011     );
	(( 8, 2),  8, 0b00101001     );
	(( 8, 3),  9, 0b001001101    );
	(( 8, 4),  9, 0b001001001    );
	(( 8, 5),  9, 0b000111111    );
	(( 8, 6),  9, 0b000111000    );
	(( 8, 7), 10, 0b0001011100   );
	(( 8, 8), 10, 0b0001001101   );
	(( 8, 9), 10, 0b0001000010   );
	(( 8,10), 10, 0b0000101111   );
	(( 8,11), 11, 0b00001000011  );
	(( 8,12), 11, 0b00000110000  );
	(( 8,13), 12, 0b000000110101 );
	(( 8,14), 12, 0b000000100100 );
	(( 8,15), 12, 0b000000010100 );
	(( 9, 0),  9, 0b001000111    );
	(( 9, 1),  8, 0b00100010     );
	(( 9, 2),  9, 0b001000011    );
	(( 9, 3),  9, 0b000111100    );
	(( 9, 4),  9, 0b000111010    );
	(( 9, 5),  9, 0b000110001    );
	(( 9, 6), 10, 0b0001011000   );
	(( 9, 7), 10, 0b0001001100   );
	(( 9, 8), 10, 0b0001000011   );
	(( 9, 9), 11, 0b00001101010  );
	(( 9,10), 11, 0b00001000111  );
	(( 9,11), 11, 0b00000110110  );
	(( 9,12), 11, 0b00000100110  );
	(( 9,13), 12, 0b000000100111 );
	(( 9,14), 12, 0b000000010111 );
	(( 9,15), 12, 0b000000001111 );
	((10, 0), 10, 0b0001101101   );
	((10, 1),  9, 0b000110101    );
	((10, 2),  9, 0b000110011    );
	((10, 3),  9, 0b000101111    );
	((10, 4), 10, 0b0001011010   );
	((10, 5), 10, 0b0001010010   );
	((10, 6), 10, 0b0000111010   );
	((10, 7), 10, 0b0000111001   );
	((10, 8), 10, 0b0000110000   );
	((10, 9), 11, 0b00001001000  );
	((10,10), 11, 0b00000111001  );
	((10,11), 11, 0b00000101001  );
	((10,12), 11, 0b00000010111  );
	((10,13), 12, 0b000000011011 );
	((10,14), 13, 0b0000000111110);
	((10,15), 12, 0b000000001001 );
	((11, 0), 10, 0b0001010110   );
	((11, 1),  9, 0b000101010    );
	((11, 2),  9, 0b000101000    );
	((11, 3),  9, 0b000100101    );
	((11, 4), 10, 0b0001000110   );
	((11, 5), 10, 0b0001000000   );
	((11, 6), 10, 0b0000110100   );
	((11, 7), 10, 0b0000101011   );
	((11, 8), 11, 0b00001000110  );
	((11, 9), 11, 0b00000110111  );
	((11,10), 11, 0b00000101010  );
	((11,11), 11, 0b00000011001  );
	((11,12), 12, 0b000000011101 );
	((11,13), 12, 0b000000010010 );
	((11,14), 12, 0b000000001011 );
	((11,15), 13, 0b0000000001011);
	((12, 0), 11, 0b00001110110  );
	((12, 1), 10, 0b0001000100   );
	((12, 2),  9, 0b000011110    );
	((12, 3), 10, 0b0000110111   );
	((12, 4), 10, 0b0000110010   );
	((12, 5), 10, 0b0000101110   );
	((12, 6), 11, 0b00001001010  );
	((12, 7), 11, 0b00001000001  );
	((12, 8), 11, 0b00000110001  );
	((12, 9), 11, 0b00000100111  );
	((12,10), 11, 0b00000011000  );
	((12,11), 11, 0b00000010000  );
	((12,12), 12, 0b000000010110 );
	((12,13), 12, 0b000000001101 );
	((12,14), 13, 0b0000000001110);
	((12,15), 13, 0b0000000000111);
	((13, 0), 11, 0b00001011011  );
	((13, 1), 10, 0b0000101100   );
	((13, 2), 10, 0b0000100111   );
	((13, 3), 10, 0b0000100110   );
	((13, 4), 10, 0b0000100010   );
	((13, 5), 11, 0b00000111111  );
	((13, 6), 11, 0b00000110100  );
	((13, 7), 11, 0b00000101101  );
	((13, 8), 11, 0b00000011111  );
	((13, 9), 12, 0b000000110100 );
	((13,10), 12, 0b000000011100 );
	((13,11), 12, 0b000000010011 );
	((13,12), 12, 0b000000001110 );
	((13,13), 12, 0b000000001000 );
	((13,14), 13, 0b0000000001001);
	((13,15), 13, 0b0000000000011);
	((14, 0), 12, 0b000001111011 );
	((14, 1), 11, 0b00000111100  );
	((14, 2), 11, 0b00000111010  );
	((14, 3), 11, 0b00000110101  );
	((14, 4), 11, 0b00000101111  );
	((14, 5), 11, 0b00000101011  );
	((14, 6), 11, 0b00000100000  );
	((14, 7), 11, 0b00000010110  );
	((14, 8), 12, 0b000000100101 );
	((14, 9), 12, 0b000000011000 );
	((14,10), 12, 0b000000010001 );
	((14,11), 12, 0b000000001100 );
	((14,12), 13, 0b0000000001111);
	((14,13), 13, 0b0000000001010);
	((14,14), 12, 0b000000000010 );
	((14,15), 13, 0b0000000000001);
	((15, 0), 12, 0b000001000111 );
	((15, 1), 11, 0b00000100101  );
	((15, 2), 11, 0b00000100010  );
	((15, 3), 11, 0b00000011110  );
	((15, 4), 11, 0b00000011100  );
	((15, 5), 11, 0b00000010100  );
	((15, 6), 11, 0b00000010001  );
	((15, 7), 12, 0b000000011010 );
	((15, 8), 12, 0b000000010101 );
	((15, 9), 12, 0b000000010000 );
	((15,10), 12, 0b000000001010 );
	((15,11), 12, 0b000000000110 );
	((15,12), 13, 0b0000000001000);
	((15,13), 13, 0b0000000000110);
	((15,14), 13, 0b0000000000010);
	((15,15), 13, 0b0000000000000);
|];;

let ht16 = [|
	(( 0, 0),  1,0b1                );
	(( 0, 1),  4,0b0101             );
	(( 0, 2),  6,0b001110           );
	(( 0, 3),  8,0b00101100         );
	(( 0, 4),  9,0b001001010        );
	(( 0, 5),  9,0b000111111        );
	(( 0, 6), 10,0b0001101110       );
	(( 0, 7), 10,0b0001011101       );
	(( 0, 8), 11,0b00010101100      );
	(( 0, 9), 11,0b00010010101      );
	(( 0,10), 11,0b00010001010      );
	(( 0,11), 12,0b000011110010     );
	(( 0,12), 12,0b000011100001     );
	(( 0,13), 12,0b000011000011     );
	(( 0,14), 13,0b0000101111000    );
	(( 0,15),  9,0b000010001        );
	(( 1, 0),  3,0b011              );
	(( 1, 1),  4,0b0100             );
	(( 1, 2),  6,0b001100           );
	(( 1, 3),  7,0b0010100          );
	(( 1, 4),  8,0b00100011         );
	(( 1, 5),  9,0b000111110        );
	(( 1, 6),  9,0b000110101        );
	(( 1, 7),  9,0b000101111        );
	(( 1, 8), 10,0b0001010011       );
	(( 1, 9), 10,0b0001001011       );
	(( 1,10), 10,0b0001000100       );
	(( 1,11), 11,0b00001110111      );
	(( 1,12), 12,0b000011001001     );
	(( 1,13), 11,0b00001101011      );
	(( 1,14), 12,0b000011001111     );
	(( 1,15),  8,0b00001001         );
	(( 2, 0),  6,0b001111           );
	(( 2, 1),  6,0b001101           );
	(( 2, 2),  7,0b0010111          );
	(( 2, 3),  8,0b00100110         );
	(( 2, 4),  9,0b001000011        );
	(( 2, 5),  9,0b000111010        );
	(( 2, 6), 10,0b0001100111       );
	(( 2, 7), 10,0b0001011010       );
	(( 2, 8), 11,0b00010100001      );
	(( 2, 9), 10,0b0001001000       );
	(( 2,10), 11,0b00001111111      );
	(( 2,11), 11,0b00001110101      );
	(( 2,12), 11,0b00001101110      );
	(( 2,13), 12,0b000011010001     );
	(( 2,14), 12,0b000011001110     );
	(( 2,15),  9,0b000010000        );
	(( 3, 0),  8,0b00101101         );
	(( 3, 1),  7,0b0010101          );
	(( 3, 2),  8,0b00100111         );
	(( 3, 3),  9,0b001000101        );
	(( 3, 4),  9,0b001000000        );
	(( 3, 5), 10,0b0001110010       );
	(( 3, 6), 10,0b0001100011       );
	(( 3, 7), 10,0b0001010111       );
	(( 3, 8), 11,0b00010011110      );
	(( 3, 9), 11,0b00010001100      );
	(( 3,10), 12,0b000011111100     );
	(( 3,11), 12,0b000011010100     );
	(( 3,12), 12,0b000011000111     );
	(( 3,13), 13,0b0000110000011    );
	(( 3,14), 13,0b0000101101101    );
	(( 3,15), 10,0b0000011010       );
	(( 4, 0),  9,0b001001011        );
	(( 4, 1),  8,0b00100100         );
	(( 4, 2),  9,0b001000100        );
	(( 4, 3),  9,0b001000001        );
	(( 4, 4), 10,0b0001110011       );
	(( 4, 5), 10,0b0001100101       );
	(( 4, 6), 11,0b00010110011      );
	(( 4, 7), 11,0b00010100100      );
	(( 4, 8), 11,0b00010011011      );
	(( 4, 9), 12,0b000100001000     );
	(( 4,10), 12,0b000011110110     );
	(( 4,11), 12,0b000011100010     );
	(( 4,12), 13,0b0000110001011    );
	(( 4,13), 13,0b0000101111110    );
	(( 4,14), 13,0b0000101101010    );
	(( 4,15),  9,0b000001001        );
	(( 5, 0),  9,0b001000010        );
	(( 5, 1),  8,0b00011110         );
	(( 5, 2),  9,0b000111011        );
	(( 5, 3),  9,0b000111000        );
	(( 5, 4), 10,0b0001100110       );
	(( 5, 5), 11,0b00010111001      );
	(( 5, 6), 11,0b00010101101      );
	(( 5, 7), 12,0b000100001001     );
	(( 5, 8), 11,0b00010001110      );
	(( 5, 9), 12,0b000011111101     );
	(( 5,10), 12,0b000011101000     );
	(( 5,11), 13,0b0000110010000    );
	(( 5,12), 13,0b0000110000100    );
	(( 5,13), 13,0b0000101111010    );
	(( 5,14), 14,0b00000110111101   );
	(( 5,15), 10,0b0000010000       );
	(( 6, 0), 10,0b0001101111       );
	(( 6, 1),  9,0b000110110        );
	(( 6, 2),  9,0b000110100        );
	(( 6, 3), 10,0b0001100100       );
	(( 6, 4), 11,0b00010111000      );
	(( 6, 5), 11,0b00010110010      );
	(( 6, 6), 11,0b00010100000      );
	(( 6, 7), 11,0b00010000101      );
	(( 6, 8), 12,0b000100000001     );
	(( 6, 9), 12,0b000011110100     );
	(( 6,10), 12,0b000011100100     );
	(( 6,11), 12,0b000011011001     );
	(( 6,12), 13,0b0000110000001    );
	(( 6,13), 13,0b0000101101110    );
	(( 6,14), 14,0b00001011001011   );
	(( 6,15), 10,0b0000001010       );
	(( 7, 0), 10,0b0001100010       );
	(( 7, 1),  9,0b000110000        );
	(( 7, 2), 10,0b0001011011       );
	(( 7, 3), 10,0b0001011000       );
	(( 7, 4), 11,0b00010100101      );
	(( 7, 5), 11,0b00010011101      );
	(( 7, 6), 11,0b00010010100      );
	(( 7, 7), 12,0b000100000101     );
	(( 7, 8), 12,0b000011111000     );
	(( 7, 9), 13,0b0000110010111    );
	(( 7,10), 13,0b0000110001101    );
	(( 7,11), 13,0b0000101110100    );
	(( 7,12), 13,0b0000101111100    );
	(( 7,13), 15,0b000001101111001  );
	(( 7,14), 15,0b000001101110100  );
	(( 7,15), 10,0b0000001000       );
	(( 8, 0), 10,0b0001010101       );
	(( 8, 1), 10,0b0001010100       );
	(( 8, 2), 10,0b0001010001       );
	(( 8, 3), 11,0b00010011111      );
	(( 8, 4), 11,0b00010011100      );
	(( 8, 5), 11,0b00010001111      );
	(( 8, 6), 12,0b000100000100     );
	(( 8, 7), 12,0b000011111001     );
	(( 8, 8), 13,0b0000110101011    );
	(( 8, 9), 13,0b0000110010001    );
	(( 8,10), 13,0b0000110001000    );
	(( 8,11), 13,0b0000101111111    );
	(( 8,12), 14,0b00001011010111   );
	(( 8,13), 14,0b00001011001001   );
	(( 8,14), 14,0b00001011000100   );
	(( 8,15), 10,0b0000000111       );
	(( 9, 0), 11,0b00010011010      );
	(( 9, 1), 10,0b0001001100       );
	(( 9, 2), 10,0b0001001001       );
	(( 9, 3), 11,0b00010001101      );
	(( 9, 4), 11,0b00010000011      );
	(( 9, 5), 12,0b000100000000     );
	(( 9, 6), 12,0b000011110101     );
	(( 9, 7), 13,0b0000110101010    );
	(( 9, 8), 13,0b0000110010110    );
	(( 9, 9), 13,0b0000110001010    );
	(( 9,10), 13,0b0000110000000    );
	(( 9,11), 14,0b00001011011111   );
	(( 9,12), 13,0b0000101100111    );
	(( 9,13), 14,0b00001011000110   );
	(( 9,14), 13,0b0000101100000    );
	(( 9,15), 11,0b00000001011      );
	((10, 0), 11,0b00010001011      );
	((10, 1), 11,0b00010000001      );
	((10, 2), 10,0b0001000011       );
	((10, 3), 11,0b00001111101      );
	((10, 4), 12,0b000011110111     );
	((10, 5), 12,0b000011101001     );
	((10, 6), 12,0b000011100101     );
	((10, 7), 12,0b000011011011     );
	((10, 8), 13,0b0000110001001    );
	((10, 9), 14,0b00001011100111   );
	((10,10), 14,0b00001011100001   );
	((10,11), 14,0b00001011010000   );
	((10,12), 15,0b000001101110101  );
	((10,13), 15,0b000001101110010  );
	((10,14), 14,0b00000110110111   );
	((10,15), 10,0b0000000100       );
	((11, 0), 12,0b000011110011     );
	((11, 1), 11,0b00001111000      );
	((11, 2), 11,0b00001110110      );
	((11, 3), 11,0b00001110011      );
	((11, 4), 12,0b000011100011     );
	((11, 5), 12,0b000011011111     );
	((11, 6), 13,0b0000110001100    );
	((11, 7), 14,0b00001011101010   );
	((11, 8), 14,0b00001011100110   );
	((11, 9), 14,0b00001011100000   );
	((11,10), 14,0b00001011010001   );
	((11,11), 14,0b00001011001000   );
	((11,12), 14,0b00001011000010   );
	((11,13), 13,0b0000011011111    );
	((11,14), 14,0b00000110110100   );
	((11,15), 11,0b00000000110      );
	((12, 0), 12,0b000011001010     );
	((12, 1), 12,0b000011100000     );
	((12, 2), 12,0b000011011110     );
	((12, 3), 12,0b000011011010     );
	((12, 4), 12,0b000011011000     );
	((12, 5), 13,0b0000110000101    );
	((12, 6), 13,0b0000110000010    );
	((12, 7), 13,0b0000101111101    );
	((12, 8), 13,0b0000101101100    );
	((12, 9), 15,0b000001101111000  );
	((12,10), 14,0b00000110111011   );
	((12,11), 14,0b00001011000011   );
	((12,12), 14,0b00000110111000   );
	((12,13), 14,0b00000110110101   );
	((12,14), 16,0b0000011011000000 );
	((12,15), 11,0b00000000100      );
	((13, 0), 14,0b00001011101011   );
	((13, 1), 12,0b000011010011     );
	((13, 2), 12,0b000011010010     );
	((13, 3), 12,0b000011010000     );
	((13, 4), 13,0b0000101110010    );
	((13, 5), 13,0b0000101111011    );
	((13, 6), 14,0b00001011011110   );
	((13, 7), 14,0b00001011010011   );
	((13, 8), 14,0b00001011001010   );
	((13, 9), 16,0b0000011011000111 );
	((13,10), 15,0b000001101110011  );
	((13,11), 15,0b000001101101101  );
	((13,12), 15,0b000001101101100  );
	((13,13), 17,0b00000110110000011);
	((13,14), 15,0b000001101100001  );
	((13,15), 11,0b00000000010      );
	((14, 0), 13,0b0000101111001    );
	((14, 1), 13,0b0000101110001    );
	((14, 2), 11,0b00001100110      );
	((14, 3), 12,0b000010111011     );
	((14, 4), 14,0b00001011010110   );
	((14, 5), 14,0b00001011010010   );
	((14, 6), 13,0b0000101100110    );
	((14, 7), 14,0b00001011000111   );
	((14, 8), 14,0b00001011000101   );
	((14, 9), 15,0b000001101100010  );
	((14,10), 16,0b0000011011000110 );
	((14,11), 15,0b000001101100111  );
	((14,12), 17,0b00000110110000010);
	((14,13), 15,0b000001101100110  );
	((14,14), 14,0b00000110110010   );
	((14,15), 11,0b00000000000      );
	((15, 0),  9,0b000001100        );
	((15, 1),  8,0b00001010         );
	((15, 2),  8,0b00000111         );
	((15, 3),  9,0b000001011        );
	((15, 4),  9,0b000001010        );
	((15, 5), 10,0b0000010001       );
	((15, 6), 10,0b0000001011       );
	((15, 7), 10,0b0000001001       );
	((15, 8), 11,0b00000001101      );
	((15, 9), 11,0b00000001100      );
	((15,10), 11,0b00000001010      );
	((15,11), 11,0b00000000111      );
	((15,12), 11,0b00000000101      );
	((15,13), 11,0b00000000011      );
	((15,14), 11,0b00000000001      );
	((15,15),  8,0b00000011         );
|];;

let ht17 = ht16;;
let ht18 = ht16;;
let ht19 = ht16;;
let ht20 = ht16;;
let ht21 = ht16;;
let ht22 = ht16;;
let ht23 = ht16;;

let   ht24   =   [|
	(( 0, 0),  4, 0b1111        );
	(( 0, 1),  4, 0b1101        );
	(( 0, 2),  6, 0b101110      );
	(( 0, 3),  7, 0b1010000     );
	(( 0, 4),  8, 0b10010010    );
	(( 0, 5),  9, 0b100000110   );
	(( 0, 6),  9, 0b011111000   );
	(( 0, 7), 10, 0b0110110010  );
	(( 0, 8), 10, 0b0110101010  );
	(( 0, 9), 11, 0b01010011101 );
	(( 0,10), 11, 0b01010001101 );
	(( 0,11), 11, 0b01010001001 );
	(( 0,12), 11, 0b01001101101 );
	(( 0,13), 11, 0b01000000101 );
	(( 0,14), 12, 0b010000001000);
	(( 0,15),  9, 0b001011000   );
	(( 1, 0),  4, 0b1110        );
	(( 1, 1),  4, 0b1100        );
	(( 1, 2),  5, 0b10101       );
	(( 1, 3),  6, 0b100110      );
	(( 1, 4),  7, 0b1000111     );
	(( 1, 5),  8, 0b10000010    );
	(( 1, 6),  8, 0b01111010    );
	(( 1, 7),  9, 0b011011000   );
	(( 1, 8),  9, 0b011010001   );
	(( 1, 9),  9, 0b011000110   );
	(( 1,10), 10, 0b0101000111  );
	(( 1,11), 10, 0b0101011001  );
	(( 1,12), 10, 0b0100111111  );
	(( 1,13), 10, 0b0100101001  );
	(( 1,14), 10, 0b0100010111  );
	(( 1,15),  8, 0b00101010    );
	(( 2, 0),  6, 0b101111      );
	(( 2, 1),  5, 0b10110       );
	(( 2, 2),  6, 0b101001      );
	(( 2, 3),  7, 0b1001010     );
	(( 2, 4),  7, 0b1000100     );
	(( 2, 5),  8, 0b10000000    );
	(( 2, 6),  8, 0b01111000    );
	(( 2, 7),  9, 0b011011101   );
	(( 2, 8),  9, 0b011001111   );
	(( 2, 9),  9, 0b011000010   );
	(( 2,10),  9, 0b010110110   );
	(( 2,11), 10, 0b0101010100  );
	(( 2,12), 10, 0b0100111011  );
	(( 2,13), 10, 0b0100100111  );
	(( 2,14), 11, 0b01000011101 );
	(( 2,15),  7, 0b0010010     );
	(( 3, 0),  7, 0b1010001     );
	(( 3, 1),  6, 0b100111      );
	(( 3, 2),  7, 0b1001011     );
	(( 3, 3),  7, 0b1000110     );
	(( 3, 4),  8, 0b10000110    );
	(( 3, 5),  8, 0b01111101    );
	(( 3, 6),  8, 0b01110100    );
	(( 3, 7),  9, 0b011011100   );
	(( 3, 8),  9, 0b011001100   );
	(( 3, 9),  9, 0b010111110   );
	(( 3,10),  9, 0b010110010   );
	(( 3,11), 10, 0b0101000101  );
	(( 3,12), 10, 0b0100110111  );
	(( 3,13), 10, 0b0100100101  );
	(( 3,14), 10, 0b0100001111  );
	(( 3,15),  7, 0b0010000     );
	(( 4, 0),  8, 0b10010011    );
	(( 4, 1),  7, 0b1001000     );
	(( 4, 2),  7, 0b1000101     );
	(( 4, 3),  8, 0b10000111    );
	(( 4, 4),  8, 0b01111111    );
	(( 4, 5),  8, 0b01110110    );
	(( 4, 6),  8, 0b01110000    );
	(( 4, 7),  9, 0b011010010   );
	(( 4, 8),  9, 0b011001000   );
	(( 4, 9),  9, 0b010111100   );
	(( 4,10), 10, 0b0101100000  );
	(( 4,11), 10, 0b0101000011  );
	(( 4,12), 10, 0b0100110010  );
	(( 4,13), 10, 0b0100011101  );
	(( 4,14), 11, 0b01000011100 );
	(( 4,15),  7, 0b0001110     );
	(( 5, 0),  9, 0b100000111   );
	(( 5, 1),  7, 0b1000010     );
	(( 5, 2),  8, 0b10000001    );
	(( 5, 3),  8, 0b01111110    );
	(( 5, 4),  8, 0b01110111    );
	(( 5, 5),  8, 0b01110010    );
	(( 5, 6),  9, 0b011010110   );
	(( 5, 7),  9, 0b011001010   );
	(( 5, 8),  9, 0b011000000   );
	(( 5, 9),  9, 0b010110100   );
	(( 5,10), 10, 0b0101010101  );
	(( 5,11), 10, 0b0100111101  );
	(( 5,12), 10, 0b0100101101  );
	(( 5,13), 10, 0b0100011001  );
	(( 5,14), 10, 0b0100000110  );
	(( 5,15),  7, 0b0001100     );
	(( 6, 0),  9, 0b011111001   );
	(( 6, 1),  8, 0b01111011    );
	(( 6, 2),  8, 0b01111001    );
	(( 6, 3),  8, 0b01110101    );
	(( 6, 4),  8, 0b01110001    );
	(( 6, 5),  9, 0b011010111   );
	(( 6, 6),  9, 0b011001110   );
	(( 6, 7),  9, 0b011000011   );
	(( 6, 8),  9, 0b010111001   );
	(( 6, 9), 10, 0b0101011011  );
	(( 6,10), 10, 0b0101001010  );
	(( 6,11), 10, 0b0100110100  );
	(( 6,12), 10, 0b0100100011  );
	(( 6,13), 10, 0b0100010000  );
	(( 6,14), 11, 0b01000001000 );
	(( 6,15),  7, 0b0001010     );
	(( 7, 0), 10, 0b0110110011  );
	(( 7, 1),  8, 0b01110011    );
	(( 7, 2),  8, 0b01101111    );
	(( 7, 3),  8, 0b01101101    );
	(( 7, 4),  9, 0b011010011   );
	(( 7, 5),  9, 0b011001011   );
	(( 7, 6),  9, 0b011000100   );
	(( 7, 7),  9, 0b010111011   );
	(( 7, 8), 10, 0b0101100001  );
	(( 7, 9), 10, 0b0101001100  );
	(( 7,10), 10, 0b0100111001  );
	(( 7,11), 10, 0b0100101010  );
	(( 7,12), 10, 0b0100011011  );
	(( 7,13), 11, 0b01000010011 );
	(( 7,14), 11, 0b00101111101 );
	(( 7,15),  8, 0b00010001    );
	(( 8, 0), 10, 0b0110101011  );
	(( 8, 1),  9, 0b011010100   );
	(( 8, 2),  9, 0b011010000   );
	(( 8, 3),  9, 0b011001101   );
	(( 8, 4),  9, 0b011001001   );
	(( 8, 5),  9, 0b011000001   );
	(( 8, 6),  9, 0b010111010   );
	(( 8, 7),  9, 0b010110001   );
	(( 8, 8),  9, 0b010101001   );
	(( 8, 9), 10, 0b0101000000  );
	(( 8,10), 10, 0b0100101111  );
	(( 8,11), 10, 0b0100011110  );
	(( 8,12), 10, 0b0100001100  );
	(( 8,13), 11, 0b01000000010 );
	(( 8,14), 11, 0b00101111001 );
	(( 8,15),  8, 0b00010000    );
	(( 9, 0), 10, 0b0101001111  );
	(( 9, 1),  9, 0b011000111   );
	(( 9, 2),  9, 0b011000101   );
	(( 9, 3),  9, 0b010111111   );
	(( 9, 4),  9, 0b010111101   );
	(( 9, 5),  9, 0b010110101   );
	(( 9, 6),  9, 0b010101110   );
	(( 9, 7), 10, 0b0101001101  );
	(( 9, 8), 10, 0b0101000001  );
	(( 9, 9), 10, 0b0100110001  );
	(( 9,10), 10, 0b0100100001  );
	(( 9,11), 10, 0b0100010011  );
	(( 9,12), 11, 0b01000001001 );
	(( 9,13), 11, 0b00101111011 );
	(( 9,14), 11, 0b00101110011 );
	(( 9,15),  8, 0b00001011    );
	((10, 0), 11, 0b01010011100 );
	((10, 1),  9, 0b010111000   );
	((10, 2),  9, 0b010110111   );
	((10, 3),  9, 0b010110011   );
	((10, 4),  9, 0b010101111   );
	((10, 5), 10, 0b0101011000  );
	((10, 6), 10, 0b0101001011  );
	((10, 7), 10, 0b0100111010  );
	((10, 8), 10, 0b0100110000  );
	((10, 9), 10, 0b0100100010  );
	((10,10), 10, 0b0100010101  );
	((10,11), 11, 0b01000010010 );
	((10,12), 11, 0b00101111111 );
	((10,13), 11, 0b00101110101 );
	((10,14), 11, 0b00101101110 );
	((10,15),  8, 0b00001010    );
	((11, 0), 11, 0b01010001100 );
	((11, 1), 10, 0b0101011010  );
	((11, 2),  9, 0b010101011   );
	((11, 3),  9, 0b010101000   );
	((11, 4),  9, 0b010100100   );
	((11, 5), 10, 0b0100111110  );
	((11, 6), 10, 0b0100110101  );
	((11, 7), 10, 0b0100101011  );
	((11, 8), 10, 0b0100011111  );
	((11, 9), 10, 0b0100010100  );
	((11,10), 10, 0b0100000111  );
	((11,11), 11, 0b01000000001 );
	((11,12), 11, 0b00101110111 );
	((11,13), 11, 0b00101110000 );
	((11,14), 11, 0b00101101010 );
	((11,15),  8, 0b00000110    );
	((12, 0), 11, 0b01010001000 );
	((12, 1), 10, 0b0101000010  );
	((12, 2), 10, 0b0100111100  );
	((12, 3), 10, 0b0100111000  );
	((12, 4), 10, 0b0100110011  );
	((12, 5), 10, 0b0100101110  );
	((12, 6), 10, 0b0100100100  );
	((12, 7), 10, 0b0100011100  );
	((12, 8), 10, 0b0100001101  );
	((12, 9), 10, 0b0100000101  );
	((12,10), 11, 0b01000000000 );
	((12,11), 11, 0b00101111000 );
	((12,12), 11, 0b00101110010 );
	((12,13), 11, 0b00101101100 );
	((12,14), 11, 0b00101100111 );
	((12,15),  8, 0b00000100    );
	((13, 0), 11, 0b01001101100 );
	((13, 1), 10, 0b0100101100  );
	((13, 2), 10, 0b0100101000  );
	((13, 3), 10, 0b0100100110  );
	((13, 4), 10, 0b0100100000  );
	((13, 5), 10, 0b0100011010  );
	((13, 6), 10, 0b0100010001  );
	((13, 7), 10, 0b0100001010  );
	((13, 8), 11, 0b01000000011 );
	((13, 9), 11, 0b00101111100 );
	((13,10), 11, 0b00101110110 );
	((13,11), 11, 0b00101110001 );
	((13,12), 11, 0b00101101101 );
	((13,13), 11, 0b00101101001 );
	((13,14), 11, 0b00101100101 );
	((13,15),  8, 0b00000010    );
	((14, 0), 12, 0b010000001001);
	((14, 1), 10, 0b0100011000  );
	((14, 2), 10, 0b0100010110  );
	((14, 3), 10, 0b0100010010  );
	((14, 4), 10, 0b0100001011  );
	((14, 5), 10, 0b0100001000  );
	((14, 6), 10, 0b0100000011  );
	((14, 7), 11, 0b00101111110 );
	((14, 8), 11, 0b00101111010 );
	((14, 9), 11, 0b00101110100 );
	((14,10), 11, 0b00101101111 );
	((14,11), 11, 0b00101101011 );
	((14,12), 11, 0b00101101000 );
	((14,13), 11, 0b00101100110 );
	((14,14), 11, 0b00101100100 );
	((14,15),  8, 0b00000000    );
	((15, 0),  8, 0b00101011    );
	((15, 1),  7, 0b0010100     );
	((15, 2),  7, 0b0010011     );
	((15, 3),  7, 0b0010001     );
	((15, 4),  7, 0b0001111     );
	((15, 5),  7, 0b0001101     );
	((15, 6),  7, 0b0001011     );
	((15, 7),  7, 0b0001001     );
	((15, 8),  7, 0b0000111     );
	((15, 9),  7, 0b0000110     );
	((15,10),  7, 0b0000100     );
	((15,11),  8, 0b00000111    );
	((15,12),  8, 0b00000101    );
	((15,13),  8, 0b00000011    );
	((15,14),  8, 0b00000001    );
	((15,15),  4, 0b0011        );
|];;

let ht25 = ht24;;
let ht26 = ht24;;
let ht27 = ht24;;
let ht28 = ht24;;
let ht29 = ht24;;
let ht30 = ht24;;
let ht31 = ht24;;


(* Count1 tables *)
let htA = [|
	((0,0,0,0), 1, 0b1     );
	((0,0,0,1), 4, 0b0101  );
	((0,0,1,0), 4, 0b0100  );
	((0,0,1,1), 5, 0b00101 );
	((0,1,0,0), 4, 0b0110  );
	((0,1,0,1), 6, 0b000101);
	((0,1,1,0), 5, 0b00100 );
	((0,1,1,1), 6, 0b000100);
	((1,0,0,0), 4, 0b0111  );
	((1,0,0,1), 5, 0b00011 );
	((1,0,1,0), 5, 0b00110 );
	((1,0,1,1), 6, 0b000000);
	((1,1,0,0), 5, 0b00111 );
	((1,1,0,1), 6, 0b000010);
	((1,1,1,0), 6, 0b000011);
	((1,1,1,1), 6, 0b000001);
|];;
let htB = [|
	((0,0,0,0), 4, 0b1111);
	((0,0,0,1), 4, 0b1110);
	((0,0,1,0), 4, 0b1101);
	((0,0,1,1), 4, 0b1100);
	((0,1,0,0), 4, 0b1011);
	((0,1,0,1), 4, 0b1010);
	((0,1,1,0), 4, 0b1001);
	((0,1,1,1), 4, 0b1000);
	((1,0,0,0), 4, 0b0111);
	((1,0,0,1), 4, 0b0110);
	((1,0,1,0), 4, 0b0101);
	((1,0,1,1), 4, 0b0100);
	((1,1,0,0), 4, 0b0011);
	((1,1,0,1), 4, 0b0010);
	((1,1,1,0), 4, 0b0001);
	((1,1,1,1), 4, 0b0000);
|]


 let make_huffman_tree ht len = 
	 if ht = [ || ] then ( 
		 [ || ] 
	 ) else ( 
		 let array_len = 1 lsl len in 
		 let out_array = Array.make array_len Zero in 

		 let rec find_spot current_out value orig_bits bits index = ( 
			 if bits < = len then ( 
				 ( * Spam up this level
let make_huffman_tree ht len =
	if ht = [||] then (
		[||]
	) else (
		let array_len = 1 lsl len in
		let out_array = Array.make array_len Zero in

		let rec find_spot current_out value orig_bits bits index = (
			if bits <= len then (
				(* Spam up this level *)
				let pad_bits = len - bits in
				let base = index lsl pad_bits in
				for add = 0 to (1 lsl pad_bits) - 1 do
					current_out.(base + add) <- One (value, pad_bits)
				done;
			) else (
				(* It's in a sub-array *)
				let extra_bits = bits - len in
				let current_index = index lsr extra_bits in
				match current_out.(current_index) with
				| Zero -> (
					(* Make a new array *)
					let new_out = Array.make array_len Zero in
					let new_index = (index lxor (current_index lsl extra_bits)) in
					find_spot new_out value orig_bits extra_bits new_index;
					current_out.(current_index) <- Many new_out
				)
				| One _ -> (
					(* This is BAD *)
					raise (Failure "Huffman table specification incorrect")
				)
				| Many new_out -> (
					(* Add to an already-existing array *)
					let new_index = (index lxor (current_index lsl extra_bits)) in
					find_spot new_out value orig_bits extra_bits new_index;
				)
			)
		) in

		Array.iter (fun (value, bits, index) ->
			find_spot out_array value bits bits index
		) ht;

		(* Make a new version of this with onemany_t *)
		let rec convert_to_onemany = function
			| Zero -> raise (Failure "Huffman table incomplete")
			| One x -> Single x
			| Many y -> Multiple (Array.map convert_to_onemany y)
		in

		Array.map convert_to_onemany out_array
	)
;;
*)

This is the safe version of the huffman_decode function . It is not useful because there is no MP3 Huffman table with > 30 bits per word

 let huffman_decode_safe ( r_str , r_at ) ht bits = 
	 let rec search_table ( r_str_now , r_at_now ) ht_now = ( 
		 let ( first_bits , ( r_str2 , r_at2 ) ) = read_bits_overflow ( r_str_now , r_at_now ) bits in 
		 match ht_now.(first_bits ) with 
		 | Single ( x , bits ) - > ( 
			 ( x , ( r_str2 , r_at2 - bits ) ) 
		 ) 
		 | Multiple ht_new - > ( 
			 search_table ( r_str2 , r_at2 ) ht_new 
		 ) 
	 ) in 
	 search_table ( r_str , r_at ) ht 
 ; ; 

let huffman_decode_safe (r_str, r_at) ht bits =
	let rec search_table (r_str_now, r_at_now) ht_now = (
		let (first_bits, (r_str2, r_at2)) = read_bits_overflow (r_str_now, r_at_now) bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			(x, (r_str2, r_at2 - bits))
		)
		| Multiple ht_new -> (
			search_table (r_str2, r_at2) ht_new
		)
	) in
	search_table (r_str, r_at) ht
;;
*)


 let huffman_decode ( r_str , r_at ) ht bits = 

	 let rec search_table ( r_str_now , r_at_now ) ht_now = ( 
		 let ( first_bits , ( r_str2 , r_at2 ) ) = read_bits_overflow_unsafe ( r_str_now , r_at_now ) bits in 
		 match ht_now.(first_bits ) with 
		 | Single ( x , bits ) - > ( 
			 ( * This one 's it !
let huffman_decode (r_str, r_at) ht bits =

	let rec search_table (r_str_now, r_at_now) ht_now = (
		let (first_bits, (r_str2, r_at2)) = read_bits_overflow_unsafe (r_str_now, r_at_now) bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			(* This one's it! *)
			(x, (r_str2, r_at2 - bits))
		)
		| Multiple ht_new -> (
			(* Keep going! *)
			search_table (r_str2, r_at2) ht_new
		)
	) in
	search_table (r_str, r_at) ht
;;

let huffman_decode_ptrref s ht bits =
	let rec search_table ht_now =
		let first_bits = Ptr.Ref.get_seq_fast_overflow s bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			(* TODO: this setting looks dangerous if get_seq_fast is used *)
(*			s.Ptr.Ref.seq_at <- s.Ptr.Ref.seq_at - bits;*)
			 Printf.printf " Bits is % d ( backing up to % d in byte % d , fast is before byte % d)\n " bits ( s. Ptr . Ref.seq_at - bits ) ( ( s. Ptr . Ref.seq_at - bits ) lsr 3 ) s. Ptr . Ref.seq_get_fast_next_byte ;
			Ptr.Ref.set_seq s (s.Ptr.Ref.seq_at - bits);
			x
		)
		| Multiple ht_new -> search_table ht_new
	in
	search_table ht
;;
*)


let global_ht_bits = 8 ; ;
let global_ht = Array.map ( fun x - > make_huffman_tree x global_ht_bits ) [ | ht0 ; ht1 ; ht2 ;  ; ( *
let global_ht_linbits = [| 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;2;3;4;6;8;10;13;4;5;6;7;8;9;11;13 |];;

let global_ht_count1_bits = 6 ; ;
(*let global_ht_count1 = Array.map (fun x -> make_huffman_tree x global_ht_count1_bits) [| htA; htB |];;*)

(**
(* PRINT STUFF *)
let rec min_max_bits bits_so_far = function
	| Single (_, bits_left_over) -> (bits_so_far - bits_left_over, bits_so_far - bits_left_over)
	| Multiple things -> Array.fold_left (fun (min_so_far,max_so_far) next ->
		let (next_min,next_max) = min_max_bits (bits_so_far + global_ht_bits) next in
		(min min_so_far next_min, max max_so_far next_max)
	) (max_int,min_int) things
;;
let rec handle_tree spaces bits_so_far = function
	| Single ((x,y), leftover) -> Printf.printf "%s%2d:(%d,%d)\n" spaces (bits_so_far - leftover - 1) x y
	| Multiple things -> (
		let next_spaces = spaces ^ "  " in
		Array.iteri (fun num thing ->
			let (min_bits, max_bits) = min_max_bits bits_so_far thing in
			Printf.printf "%s%d (%d~%d):\n" spaces num min_bits max_bits;
			handle_tree next_spaces (bits_so_far + global_ht_bits) thing
		) things
	)
;;
handle_tree "" global_ht_bits (Multiple global_ht.(2));;
exit 4;;
(* !PRINT STUFF *)
**)
(**
(* NEW HT DECODE *)
  First build the binary tables
type 'a bin_tree_t = BinLeaf of 'a | BinBranch of 'a bin_tree_t * 'a bin_tree_t;;
let rec make_binary_tree num_bits_now prepend hl =
	(* If there is just one option here, return it *)
	let rec find_one = function
		| [] -> None
		| (v, bits, code) :: tl when bits = num_bits_now && code = prepend -> Some v
		| hd :: tl -> find_one tl
	in
	match find_one hl with
	| Some v -> BinLeaf v
	| None -> (
		let path_0 = make_binary_tree (succ num_bits_now) (2 * prepend + 0) hl in
		let path_1 = make_binary_tree (succ num_bits_now) (2 * prepend + 1) hl in
		BinBranch (path_0, path_1)
	)
;;
let global_ht_binary_trees = Array.map (fun ht -> make_binary_tree 0 0 (Array.to_list ht)) [| ht0; ht1; ht2; ht3; (**)ht0; ht5; ht6; ht7; ht8; ht9; ht10; ht11; ht12; ht13; (**)ht0; ht15; ht16; ht17; ht18; ht19; ht20; ht21; ht22; ht23; ht24; ht25; ht26; ht27; ht28; ht29; ht30; ht31 |];;

(* Now put the constant sub-trees in arrays *)
type 'a flat_tree_t = FlatLeaf of 'a | FlatArray of int * 'a flat_tree_t array | FlatBinary of 'a flat_tree_t * 'a flat_tree_t;;

let rec get_binary_min_max = function
	| BinLeaf _ -> (0,0)
	| BinBranch (path_0, path_1) -> (
		let (min_0, max_0) = get_binary_min_max path_0 in
		let (min_1, max_1) = get_binary_min_max path_1 in
		(1 + min min_0 min_1, 1 + max max_0 max_1)
	)
;;

let rec make_flat_tree = function
	| BinLeaf v -> FlatLeaf (v,0)
	| (BinBranch (path_0, path_1) as n) -> (
		let (min_path, max_path) = get_binary_min_max n in
		let rec flat_of_binary = function
			| BinLeaf x -> FlatLeaf (x,0)
			| BinBranch (x,y) -> FlatBinary (flat_of_binary x, flat_of_binary y)
		in
		if min_path = max_path && min_path > 1 then (
			(* Use a flat array *)
			let rec get_val i num_bits = function
				| BinLeaf v -> FlatLeaf (v,0)
				| BinBranch (path_0, path_1) when num_bits = 0 -> FlatBinary (flat_of_binary path_0, flat_of_binary path_1)
				| BinBranch (path_0, path_1) -> (
					let get_bit = 1 lsl (num_bits - 1) in
					get_val (i land (get_bit - 1)) (pred num_bits) (if i land get_bit <> 0 then path_1 else path_0)
				)
			in
			let flat_array = Array.make (1 lsl min_path) (get_val 0 min_path n) in
			(* Process the rest of the array *)
			FlatArray (min_path, flat_array)
		) else (
			(* Binary *)
			FlatBinary (make_flat_tree path_0, make_flat_tree path_1)
		)
	)
;;


let rec print_binary_tree spaces = function
	| BinLeaf (x,y) -> Printf.printf "%s(%2d,%2d)\n" spaces x y
	| BinBranch (path_0, path_1) -> (
		let next_spaces = spaces ^ "  " in
		let (min_0, max_0) = get_binary_min_max path_0 in
		Printf.printf "%s0: (%d~%d)\n" spaces min_0 max_0;
		print_binary_tree next_spaces path_0;
		let (min_1, max_1) = get_binary_min_max path_1 in
		Printf.printf "%s1: (%d~%d)\n" spaces min_1 max_1;
		print_binary_tree next_spaces path_1;
	)
;;

  This return the min and  number of bits to EITHER a leaf OR an array
let rec get_flat_min_max = function
	| FlatLeaf _ -> (0,0)
	| FlatArray _ -> (0,0)
	| FlatBinary (path_0, path_1) -> (
		let (min_0, max_0) = get_flat_min_max path_0 in
		let (min_1, max_1) = get_flat_min_max path_1 in
		(1 + min min_0 min_1, 1 + max max_0 max_1)
	)
;;
let rec print_flat_tree spaces = function
	| FlatLeaf ((x,y),back) -> Printf.printf "%s(%2d,%2d) back %d\n" spaces x y back
	| FlatBinary (path_0, path_1) -> (
		let next_spaces = spaces ^ "  " in
		let (min_0, max_0) = get_flat_min_max path_0 in
		Printf.printf "%s0: (%d~%d)\n" spaces min_0 max_0;
		print_flat_tree next_spaces path_0;
		let (min_1, max_1) = get_flat_min_max path_1 in
		Printf.printf "%s1: (%d~%d)\n" spaces min_1 max_1;
		print_flat_tree next_spaces path_1;
	)
	| FlatArray (bits, a) -> (
		Printf.printf "%sARRAY with %d bits:\n" spaces bits;
		let index_spaces = spaces ^ "  " in
		let rec_spaces = index_spaces ^ "  " in
		Array.iteri (fun i x ->
			Printf.printf "%s[%3d]:\n" index_spaces i;
			print_flat_tree rec_spaces x
		) a
	)
;;
print_flat_tree "" (make_flat_tree global_ht_binary_trees.(31));;

Array.iteri (fun i bt ->
	Printf.printf "### %d ###\n" i;
	print_binary_tree "  " bt;
) global_ht_binary_trees;;
exit 4;;
**)

  Note that the default is ( 0,1 ) , which is impossible .
(* This shouldn't create any problems, but should be easily identifiable as an error *)
let make_4bit_huffman_encode_table ht =
	let out_table = Array.make 256 (0,0b1) in
	Array.iter (fun ((x,y), l, q) -> out_table.((x lsl 4) lor (y land 15)) <- (l,q)) ht;
	out_table
;;

let make_1bit_huffman_encode_table ht =
	let out_table = Array.make 16 (0,0b1) in
	Array.iter (fun ((v,w,x,y), l, q) -> out_table.(v lsl 3 lor w lsl 2 lor x lsl 1 lor y) <- (l,q)) ht;
	out_table
;;

let global_ht_encode = Array.map ( fun x - > make_huffman_encode_table x ) [ | ht0 ; ht1 ; ht2 ;  ; ( *
(*let global_ht_encode_count1 = Array.map (fun x -> make_huffman_encode_table x) [| htA; htB |];;*)
let global_ht_encode = Array.map (fun x -> make_4bit_huffman_encode_table x) [| ht0; ht1; ht2; ht3; (**)htX; ht5; ht6; ht7; ht8; ht9; ht10; ht11; ht12; ht13; (**)htX; ht15; ht16; ht17; ht18; ht19; ht20; ht21; ht22; ht23; ht24; ht25; ht26; ht27; ht28; ht29; ht30; ht31 |];;
let global_ht_encode_count1 = Array.map (fun x -> make_1bit_huffman_encode_table x) [| htA; htB |];;



(* How long is every value encoded for each table? *)
(* This is useful when finding the smallest quantizer table without worrying about the exact encoding *)
let quant_bits = Array.mapi (fun t ht ->
	Array.init 256 (fun x -> match ht.(x) with
		| (0,1) -> too_many_bits
		| (b,_) -> (
			let linbits = (if x land 0x0F = 0x0F then global_ht_linbits.(t) else 0) + (if x land 0xF0 = 0xF0 then global_ht_linbits.(t) else 0) in
			b + linbits
		)
	)
) global_ht_encode;;
let quant_bits_count1 = Array.map (fun ht ->
	Array.init 16 (fun x -> fst ht.(x))
) global_ht_encode_count1;;


(* Do ptr things for the C part *)
  I think it would be better to swap the indexes , so the " first " index is the quantizer value and the " last " is the table
let quant_bits_ptr = Ptr.make_page (256 * 32 * 4);;
let quant_bits_ptr16 = Ptr.make_page (256 * 32 * 2);;
for tn = 0 to 32 - 1 do
	let t_now = quant_bits.(tn) in
	for qn = 0 to 256 - 1 do
		let q_now = t_now.(qn) in
(*
Array.iteri (fun tn t_now ->
	Array.iteri (fun qn q_now ->
*)
		let q_offset = 4 * (qn * 32 + tn) in
		Ptr.put_32_of_int quant_bits_ptr q_offset q_now;
		let q_offset16 = 2 * (qn * 32 + tn) in
		Ptr.put_16_of_int quant_bits_ptr16 q_offset16 q_now;
(*
	) t_now
) quant_bits;;
*)
	done
done;;

let quant_bits_count1_char_ptr = Ptr.make (16 * Array.length quant_bits_count1) 32;;
Array.iteri (fun tn t_now ->
	Array.iteri (fun qn q_now ->
		let q_offset = (qn * 2 + tn) in
		Ptr.put_8_of_int quant_bits_count1_char_ptr q_offset q_now
	) t_now
) quant_bits_count1;;











(* NEW STUFF FOR ENCODING *)
(*external simple_lookup : int -> int -> int -> int * int = "simple_lookup";;*)

external write_big_quants_test : int - > int - > int - > Ptr.t - > int - > int = " write_big_quants_test " ; ;

external write_big_to_frame : Ptr.t -> int -> int -> int -> Ptr.t -> int -> int = "mfh_write_big_to_frame_bytecode" "mfh_write_big_to_frame";;

external write_all_to_frame : Ptr.t -> int -> int -> int -> int -> int -> int -> bool -> Ptr.t -> int -> int = "mfh_write_all_to_frame_bytecode" "mfh_write_all_to_frame";;


external flni_test : Ptr.t -> int = "flni_test";;


 get_huffman ht_num int_for_processing start_left_shift 
 NOTE: count* values are actually the number of quants, NOT the number of quant pairs 
 For some reason, ht4 doesn't exist... 
 Count1 tables 
 Spam up this level 
 It's in a sub-array 
 Make a new array 
 This is BAD 
 Add to an already-existing array 
 Make a new version of this with onemany_t 
 This one's it! 
 Keep going! 
 TODO: this setting looks dangerous if get_seq_fast is used 
			s.Ptr.Ref.seq_at <- s.Ptr.Ref.seq_at - bits;
let global_ht_count1 = Array.map (fun x -> make_huffman_tree x global_ht_count1_bits) [| htA; htB |];;
*
(* PRINT STUFF 
 !PRINT STUFF 
*
(* NEW HT DECODE 
 If there is just one option here, return it 


 Now put the constant sub-trees in arrays 
 Use a flat array 
 Process the rest of the array 
 Binary 
 This shouldn't create any problems, but should be easily identifiable as an error 
let global_ht_encode_count1 = Array.map (fun x -> make_huffman_encode_table x) [| htA; htB |];;


 How long is every value encoded for each table? 
 This is useful when finding the smallest quantizer table without worrying about the exact encoding 
 Do ptr things for the C part 

Array.iteri (fun tn t_now ->
	Array.iteri (fun qn q_now ->


	) t_now
) quant_bits;;

 NEW STUFF FOR ENCODING 
external simple_lookup : int -> int -> int -> int * int = "simple_lookup";;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
	 This file is a part of mp3packer . 

	 mp3packer 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 2 of the License , or 
	 ( at your option ) any later version . 

	 mp3packer 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  ; if not , write to the Free Software 
	 Foundation , Inc. , 51 Franklin St , Fifth Floor , Boston , MA   02110 - 1301   USA 
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	This file is a part of mp3packer.

	mp3packer 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 2 of the License, or
	(at your option) any later version.

	mp3packer 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 mp3packer; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*******************************************************************************)

  Huffman tables !

open Types;;
open Pack;;

external get_huffman_c : int -> int -> int -> int = "mfh_get_huffman" "noalloc";;
let get_huffman_big num i shift = get_huffman_c num i shift;;
let get_huffman_part1 num i shift = get_huffman_c (num + 32) i shift;;


external decode_big_quants_unsafe : Ptr.t -> int -> int -> Ptr.t -> int -> int -> int -> int * int = "mfh_decode_big_quants_bytecode" "mfh_decode_big_quants";;
let decode_big_quants in_ptr in_bit_off in_bit_off_to out_ptr out_quant_off out_quant_off_to ht decoder_error_ref =
	if in_bit_off < 0 || out_quant_off < 0 || ht < 0 || ht >= 32 then (
		invalid_arg "Mp3framehuffman.decode_big_quants";
	);
	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in
	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in
	decode_big_quants_unsafe in_ptr in_bit_off use_bit_off_to out_ptr out_quant_off use_quant_off_to ht
;;

external decode_all_big_quants_unsafe : Ptr.t -> int -> Ptr.t -> int -> int -> int -> int -> int -> int -> int -> int * int = "mfh_decode_all_big_quants_bytecode" "mfh_decode_all_big_quants";;
let decode_all_big_quants in_ptr in_bit_off out_ptr in_bit_off_to count0 ht0 count1 ht1 count2 ht2 decoder_error_ref =
	if in_bit_off < 0 || ht0 < 0 || ht0 >= 32 || ht1 < 0 || ht1 >= 32 || ht2 < 0 || ht2 >= 32 then (
		invalid_arg "Mp3framehuffman.decode_all_big_quants"
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in

	let use_count0 = if count0 * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		count0
	) in

	let use_count1 = if (use_count0 + count1) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0
	) else (
		count1
	) in

	let use_count2 = if (use_count0 + use_count1 + count2) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0 - use_count1
	) else (
		count2
	) in

	decode_all_big_quants_unsafe in_ptr in_bit_off out_ptr use_bit_off_to use_count0 ht0 use_count1 ht1 use_count2 ht2
;;

external decode_count1_quants_unsafe : Ptr.t -> int -> int -> Ptr.t -> int -> int -> bool -> bool * int * int = "mfh_decode_count1_quants_bytecode" "mfh_decode_count1_quants";;
let decode_count1_quants in_ptr in_bit_off in_bit_off_to out_ptr out_quant_off out_quant_off_to ht1 decoder_error_ref =
	if in_bit_off < 0 || out_quant_off < 0 then (
		invalid_arg "Mp3framehuffman.decode_count1_quants";
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in
	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in
	let ret = decode_count1_quants_unsafe in_ptr in_bit_off use_bit_off_to out_ptr out_quant_off use_quant_off_to ht1 in
	let (_, _, new_index) = ret in
	if new_index > out_quant_off_to then (
		decoder_error_ref := true;
	);
	ret
;;

external decode_all_quants_unsafe : Ptr.t -> int -> Ptr.t -> int -> int -> int -> int -> int -> int -> int -> int -> bool -> bool * bool * int * int = "mfh_decode_all_quants_bytecode" "mfh_decode_all_quants";;
let decode_all_quants in_ptr in_bit_off out_ptr in_bit_off_to count0 ht0 count1 ht1 count2 ht2 out_quant_off_to ht1_table1 decoder_error_ref =
	if in_bit_off < 0 || ht0 < 0 || ht0 >= 32 || ht1 < 0 || ht1 >= 32 || ht2 < 0 || ht2 >= 32 then (
		invalid_arg "Mp3framehuffman.decode_all_quants"
	);

	let use_bit_off_to = if in_bit_off_to > 8 * Ptr.length in_ptr then (
		decoder_error_ref := true;
		8 * Ptr.length in_ptr
	) else (
		in_bit_off_to
	) in

	let use_count0 = if count0 * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		count0
	) in

	let use_count1 = if (use_count0 + count1) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0
	) else (
		count1
	) in

	let use_count2 = if (use_count0 + use_count1 + count2) * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2 - use_count0 - use_count1
	) else (
		count2
	) in

	let use_quant_off_to = if out_quant_off_to * 2 > Ptr.length out_ptr then (
		decoder_error_ref := true;
		Ptr.length out_ptr / 2
	) else (
		out_quant_off_to
	) in

	let ret = decode_all_quants_unsafe in_ptr in_bit_off out_ptr use_bit_off_to use_count0 ht0 use_count1 ht1 use_count2 ht2 use_quant_off_to ht1_table1 in
	let (new_error, new_overboard, new_bit_off, new_index) = ret in
	if new_index > out_quant_off_to then (
		decoder_error_ref := true;
	);
	decoder_error_ref := !decoder_error_ref || new_error;
	(new_overboard, new_bit_off, new_index)
;;


let too_many_bits = 32768;;

let htX = [||];;

let ht0 = [|
	((0,0), 0, 0b0);
|];;

let ht1 = [|
	((0,0), 1, 0b1  );
	((0,1), 3, 0b001);
	((1,0), 2, 0b01 );
	((1,1), 3, 0b000);
|];;

let ht2 = [|
	((0,0), 1, 0b1     );
	((0,1), 3, 0b010   );
	((0,2), 6, 0b000001);
	((1,0), 3, 0b011   );
	((1,1), 3, 0b001   );
	((1,2), 5, 0b00001 );
	((2,0), 5, 0b00011 );
	((2,1), 5, 0b00010 );
	((2,2), 6, 0b000000);
|];;

let ht3 = [|
	((0,0), 2, 0b11    );
	((0,1), 2, 0b10    );
	((0,2), 6, 0b000001);
	((1,0), 3, 0b001   );
	((1,1), 2, 0b01    );
	((1,2), 5, 0b00001 );
	((2,0), 5, 0b00011 );
	((2,1), 5, 0b00010 );
	((2,2), 6, 0b000000);
|];;


let ht5 = [|
	((0,0), 1, 0b1       );
	((0,1), 3, 0b010     );
	((0,2), 6, 0b000110  );
	((0,3), 7, 0b0000101 );
	((1,0), 3, 0b011     );
	((1,1), 3, 0b001     );
	((1,2), 6, 0b000100  );
	((1,3), 7, 0b0000100 );
	((2,0), 6, 0b000111  );
	((2,1), 6, 0b000101  );
	((2,2), 7, 0b0000111 );
	((2,3), 8, 0b00000001);
	((3,0), 7, 0b0000110 );
	((3,1), 6, 0b000001  );
	((3,2), 7, 0b0000001 );
	((3,3), 8, 0b00000000);
|];;

let ht6 = [|
	((0,0), 3, 0b111    );
	((0,1), 3, 0b011    );
	((0,2), 5, 0b00101  );
	((0,3), 7, 0b0000001);
	((1,0), 3, 0b110    );
	((1,1), 2, 0b10     );
	((1,2), 4, 0b0011   );
	((1,3), 5, 0b00010  );
	((2,0), 4, 0b0101   );
	((2,1), 4, 0b0100   );
	((2,2), 5, 0b00100  );
	((2,3), 6, 0b000001 );
	((3,0), 6, 0b000011 );
	((3,1), 5, 0b00011  );
	((3,2), 6, 0b000010 );
	((3,3), 7, 0b0000000);
|];;

let ht7 = [|
	((0,0), 1 , 0b1         );
	((0,1), 3 , 0b010       );
	((0,2), 6 , 0b001010    );
	((0,3), 8 , 0b00010011  );
	((0,4), 8 , 0b00010000  );
	((0,5), 9 , 0b000001010 );
	((1,0), 3 , 0b011       );
	((1,1), 4 , 0b0011      );
	((1,2), 6 , 0b000111    );
	((1,3), 7 , 0b0001010   );
	((1,4), 7 , 0b0000101   );
	((1,5), 8 , 0b00000011  );
	((2,0), 6 , 0b001011    );
	((2,1), 5 , 0b00100     );
	((2,2), 7 , 0b0001101   );
	((2,3), 8 , 0b00010001  );
	((2,4), 8 , 0b00001000  );
	((2,5), 9 , 0b000000100 );
	((3,0), 7 , 0b0001100   );
	((3,1), 7 , 0b0001011   );
	((3,2), 8 , 0b00010010  );
	((3,3), 9 , 0b000001111 );
	((3,4), 9 , 0b000001011 );
	((3,5), 9 , 0b000000010 );
	((4,0), 7 , 0b0000111   );
	((4,1), 7 , 0b0000110   );
	((4,2), 8 , 0b00001001  );
	((4,3), 9 , 0b000001110 );
	((4,4), 9 , 0b000000011 );
	((4,5), 10, 0b0000000001);
	((5,0), 8 , 0b00000110  );
	((5,1), 8 , 0b00000100  );
	((5,2), 9 , 0b000000101 );
	((5,3), 10, 0b0000000011);
	((5,4), 10, 0b0000000010);
	((5,5), 10, 0b0000000000);
|];;

let ht8 = [|
	((0,0), 2 , 0b11         );
	((0,1), 3 , 0b100        );
	((0,2), 6 , 0b000110     );
	((0,3), 8 , 0b00010010   );
	((0,4), 8 , 0b00001100   );
	((0,5), 9 , 0b000000101  );
	((1,0), 3 , 0b101        );
	((1,1), 2 , 0b01         );
	((1,2), 4 , 0b0010       );
	((1,3), 8 , 0b00010000   );
	((1,4), 8 , 0b00001001   );
	((1,5), 8 , 0b00000011   );
	((2,0), 6 , 0b000111     );
	((2,1), 4 , 0b0011       );
	((2,2), 6 , 0b000101     );
	((2,3), 8 , 0b00001110   );
	((2,4), 8 , 0b00000111   );
	((2,5), 9 , 0b000000011  );
	((3,0), 8 , 0b00010011   );
	((3,1), 8 , 0b00010001   );
	((3,2), 8 , 0b00001111   );
	((3,3), 9 , 0b000001101  );
	((3,4), 9 , 0b000001010  );
	((3,5), 10, 0b0000000100 );
	((4,0), 8 , 0b00001101   );
	((4,1), 7 , 0b0000101    );
	((4,2), 8 , 0b00001000   );
	((4,3), 9 , 0b000001011  );
	((4,4), 10, 0b0000000101 );
	((4,5), 10, 0b0000000001 );
	((5,0), 9 , 0b000001100  );
	((5,1), 8 , 0b00000100   );
	((5,2), 9 , 0b000000100  );
	((5,3), 9 , 0b000000001  );
	((5,4), 11, 0b00000000001);
	((5,5), 11, 0b00000000000);
|];;

let ht9 = [|
	((0,0), 3, 0b111      );
	((0,1), 3, 0b101      );
	((0,2), 5, 0b01001    );
	((0,3), 6, 0b001110   );
	((0,4), 8, 0b00001111 );
	((0,5), 9, 0b000000111);
	((1,0), 3, 0b110      );
	((1,1), 3, 0b100      );
	((1,2), 4, 0b0101     );
	((1,3), 5, 0b00101    );
	((1,4), 6, 0b000110   );
	((1,5), 8, 0b00000111 );
	((2,0), 4, 0b0111     );
	((2,1), 4, 0b0110     );
	((2,2), 5, 0b01000    );
	((2,3), 6, 0b001000   );
	((2,4), 7, 0b0001000  );
	((2,5), 8, 0b00000101 );
	((3,0), 6, 0b001111   );
	((3,1), 5, 0b00110    );
	((3,2), 6, 0b001001   );
	((3,3), 7, 0b0001010  );
	((3,4), 7, 0b0000101  );
	((3,5), 8, 0b00000001 );
	((4,0), 7, 0b0001011  );
	((4,1), 6, 0b000111   );
	((4,2), 7, 0b0001001  );
	((4,3), 7, 0b0000110  );
	((4,4), 8, 0b00000100 );
	((4,5), 9, 0b000000001);
	((5,0), 8, 0b00001110 );
	((5,1), 7, 0b0000100  );
	((5,2), 8, 0b00000110 );
	((5,3), 8, 0b00000010 );
	((5,4), 9, 0b000000110);
	((5,5), 9, 0b000000000);
|];;

let ht10 = [|
	((0,0),1 , 0b1          );
	((0,1),3 , 0b010        );
	((0,2),6 , 0b001010     );
	((0,3),8 , 0b00010111   );
	((0,4),9 , 0b000100011  );
	((0,5),9 , 0b000011110  );
	((0,6),9 , 0b000001100  );
	((0,7),10, 0b0000010001 );
	((1,0),3 , 0b011        );
	((1,1),4 , 0b0011       );
	((1,2),6 , 0b001000     );
	((1,3),7 , 0b0001100    );
	((1,4),8 , 0b00010010   );
	((1,5),9 , 0b000010101  );
	((1,6),8 , 0b00001100   );
	((1,7),8 , 0b00000111   );
	((2,0),6 , 0b001011     );
	((2,1),6 , 0b001001     );
	((2,2),7 , 0b0001111    );
	((2,3),8 , 0b00010101   );
	((2,4),9 , 0b000100000  );
	((2,5),10, 0b0000101000 );
	((2,6),9 , 0b000010011  );
	((2,7),9 , 0b000000110  );
	((3,0),7 , 0b0001110    );
	((3,1),7 , 0b0001101    );
	((3,2),8 , 0b00010110   );
	((3,3),9 , 0b000100010  );
	((3,4),10, 0b0000101110 );
	((3,5),10, 0b0000010111 );
	((3,6),9 , 0b000010010  );
	((3,7),10, 0b0000000111 );
	((4,0),8 , 0b00010100   );
	((4,1),8 , 0b00010011   );
	((4,2),9 , 0b000100001  );
	((4,3),10, 0b0000101111 );
	((4,4),10, 0b0000011011 );
	((4,5),10, 0b0000010110 );
	((4,6),10, 0b0000001001 );
	((4,7),10, 0b0000000011 );
	((5,0),9 , 0b000011111  );
	((5,1),9 , 0b000010110  );
	((5,2),10, 0b0000101001 );
	((5,3),10, 0b0000011010 );
	((5,4),11, 0b00000010101);
	((5,5),11, 0b00000010100);
	((5,6),10, 0b0000000101 );
	((5,7),11, 0b00000000011);
	((6,0),8 , 0b00001110   );
	((6,1),8 , 0b00001101   );
	((6,2),9 , 0b000001010  );
	((6,3),10, 0b0000001011 );
	((6,4),10, 0b0000010000 );
	((6,5),10, 0b0000000110 );
	((6,6),11, 0b00000000101);
	((6,7),11, 0b00000000001);
	((7,0),9 , 0b000001001  );
	((7,1),8 , 0b00001000   );
	((7,2),9 , 0b000000111  );
	((7,3),10, 0b0000001000 );
	((7,4),10, 0b0000000100 );
	((7,5),11, 0b00000000100);
	((7,6),11, 0b00000000010);
	((7,7),11, 0b00000000000);
|];;

let ht11 = [|
	((0,0), 2 , 0b11         );
	((0,1), 3 , 0b100        );
	((0,2), 5 , 0b01010      );
	((0,3), 7 , 0b0011000    );
	((0,4), 8 , 0b00100010   );
	((0,5), 9 , 0b000100001  );
	((0,6), 8 , 0b00010101   );
	((0,7), 9 , 0b000001111  );
	((1,0), 3 , 0b101        );
	((1,1), 3 , 0b011        );
	((1,2), 4 , 0b0100       );
	((1,3), 6 , 0b001010     );
	((1,4), 8 , 0b00100000   );
	((1,5), 8 , 0b00010001   );
	((1,6), 7 , 0b0001011    );
	((1,7), 8 , 0b00001010   );
	((2,0), 5 , 0b01011      );
	((2,1), 5 , 0b00111      );
	((2,2), 6 , 0b001101     );
	((2,3), 7 , 0b0010010    );
	((2,4), 8 , 0b00011110   );
	((2,5), 9 , 0b000011111  );
	((2,6), 8 , 0b00010100   );
	((2,7), 8 , 0b00000101   );
	((3,0), 7 , 0b0011001    );
	((3,1), 6 , 0b001011     );
	((3,2), 7 , 0b0010011    );
	((3,3), 9 , 0b000111011  );
	((3,4), 8 , 0b00011011   );
	((3,5), 10, 0b0000010010 );
	((3,6), 8 , 0b00001100   );
	((3,7), 9 , 0b000000101  );
	((4,0), 8 , 0b00100011   );
	((4,1), 8 , 0b00100001   );
	((4,2), 8 , 0b00011111   );
	((4,3), 9 , 0b000111010  );
	((4,4), 9 , 0b000011110  );
	((4,5), 10, 0b0000010000 );
	((4,6), 9 , 0b000000111  );
	((4,7), 10, 0b0000000101 );
	((5,0), 8 , 0b00011100   );
	((5,1), 8 , 0b00011010   );
	((5,2), 9 , 0b000100000  );
	((5,3), 10, 0b0000010011 );
	((5,4), 10, 0b0000010001 );
	((5,5), 11, 0b00000001111);
	((5,6), 10, 0b0000001000 );
	((5,7), 11, 0b00000001110);
	((6,0), 8 , 0b00001110   );
	((6,1), 7 , 0b0001100    );
	((6,2), 7 , 0b0001001    );
	((6,3), 8 , 0b00001101   );
	((6,4), 9 , 0b000001110  );
	((6,5), 10, 0b0000001001 );
	((6,6), 10, 0b0000000100 );
	((6,7), 10, 0b0000000001 );
	((7,0), 8 , 0b00001011   );
	((7,1), 7 , 0b0000100    );
	((7,2), 8 , 0b00000110   );
	((7,3), 9 , 0b000000110  );
	((7,4), 10, 0b0000000110 );
	((7,5), 10, 0b0000000011 );
	((7,6), 10, 0b0000000010 );
	((7,7), 10, 0b0000000000 );
|];;

let ht12 = [|
	((0,0),4 , 0b1001      );
	((0,1),3 , 0b110       );
	((0,2),5 , 0b10000     );
	((0,3),7 , 0b0100001   );
	((0,4),8 , 0b00101001  );
	((0,5),9 , 0b000100111 );
	((0,6),9 , 0b000100110 );
	((0,7),9 , 0b000011010 );
	((1,0),3 , 0b111       );
	((1,1),3 , 0b101       );
	((1,2),4 , 0b0110      );
	((1,3),5 , 0b01001     );
	((1,4),7 , 0b0010111   );
	((1,5),7 , 0b0010000   );
	((1,6),8 , 0b00011010  );
	((1,7),8 , 0b00001011  );
	((2,0),5 , 0b10001     );
	((2,1),4 , 0b0111      );
	((2,2),5 , 0b01011     );
	((2,3),6 , 0b001110    );
	((2,4),7 , 0b0010101   );
	((2,5),8 , 0b00011110  );
	((2,6),7 , 0b0001010   );
	((2,7),8 , 0b00000111  );
	((3,0),6 , 0b010001    );
	((3,1),5 , 0b01010     );
	((3,2),6 , 0b001111    );
	((3,3),6 , 0b001100    );
	((3,4),7 , 0b0010010   );
	((3,5),8 , 0b00011100  );
	((3,6),8 , 0b00001110  );
	((3,7),8 , 0b00000101  );
	((4,0),7 , 0b0100000   );
	((4,1),6 , 0b001101    );
	((4,2),7 , 0b0010110   );
	((4,3),7 , 0b0010011   );
	((4,4),8 , 0b00010010  );
	((4,5),8 , 0b00010000  );
	((4,6),8 , 0b00001001  );
	((4,7),9 , 0b000000101 );
	((5,0),8 , 0b00101000  );
	((5,1),7 , 0b0010001   );
	((5,2),8 , 0b00011111  );
	((5,3),8 , 0b00011101  );
	((5,4),8 , 0b00010001  );
	((5,5),9 , 0b000001101 );
	((5,6),8 , 0b00000100  );
	((5,7),9 , 0b000000010 );
	((6,0),8 , 0b00011011  );
	((6,1),7 , 0b0001100   );
	((6,2),7 , 0b0001011   );
	((6,3),8 , 0b00001111  );
	((6,4),8 , 0b00001010  );
	((6,5),9 , 0b000000111 );
	((6,6),9 , 0b000000100 );
	((6,7),10, 0b0000000001);
	((7,0),9 , 0b000011011 );
	((7,1),8 , 0b00001100  );
	((7,2),8 , 0b00001000  );
	((7,3),9 , 0b000001100 );
	((7,4),9 , 0b000000110 );
	((7,5),9 , 0b000000011 );
	((7,6),9 , 0b000000001 );
	((7,7),10, 0b0000000000);
|];;

let ht13 = [|
	(( 0,0 ), 1 , 0b1                  );
	(( 0,1 ), 4 , 0b0101               );
	(( 0,2 ), 6 , 0b001110             );
	(( 0,3 ), 7 , 0b0010101            );
	(( 0,4 ), 8 , 0b00100010           );
	(( 0,5 ), 9 , 0b000110011          );
	(( 0,6 ), 9 , 0b000101110          );
	(( 0,7 ), 10, 0b0001000111         );
	(( 0,8 ), 9 , 0b000101010          );
	(( 0,9 ), 10, 0b0000110100         );
	(( 0,10), 11, 0b00001000100        );
	(( 0,11), 11, 0b00000110100        );
	(( 0,12), 12, 0b000001000011       );
	(( 0,13), 12, 0b000000101100       );
	(( 0,14), 13, 0b0000000101011      );
	(( 0,15), 13, 0b0000000010011      );
	(( 1,0 ), 3 , 0b011                );
	(( 1,1 ), 4 , 0b0100               );
	(( 1,2 ), 6 , 0b001100             );
	(( 1,3 ), 7 , 0b0010011            );
	(( 1,4 ), 8 , 0b00011111           );
	(( 1,5 ), 8 , 0b00011010           );
	(( 1,6 ), 9 , 0b000101100          );
	(( 1,7 ), 9 , 0b000100001          );
	(( 1,8 ), 9 , 0b000011111          );
	(( 1,9 ), 9 , 0b000011000          );
	(( 1,10), 10, 0b0000100000         );
	(( 1,11), 10, 0b0000011000         );
	(( 1,12), 11, 0b00000011111        );
	(( 1,13), 12, 0b000000100011       );
	(( 1,14), 12, 0b000000010110       );
	(( 1,15), 12, 0b000000001110       );
	(( 2,0 ), 6 , 0b001111             );
	(( 2,1 ), 6 , 0b001101             );
	(( 2,2 ), 7 , 0b0010111            );
	(( 2,3 ), 8 , 0b00100100           );
	(( 2,4 ), 9 , 0b000111011          );
	(( 2,5 ), 9 , 0b000110001          );
	(( 2,6 ), 10, 0b0001001101         );
	(( 2,7 ), 10, 0b0001000001         );
	(( 2,8 ), 9 , 0b000011101          );
	(( 2,9 ), 10, 0b0000101000         );
	(( 2,10), 10, 0b0000011110         );
	(( 2,11), 11, 0b00000101000        );
	(( 2,12), 11, 0b00000011011        );
	(( 2,13), 12, 0b000000100001       );
	(( 2,14), 13, 0b0000000101010      );
	(( 2,15), 13, 0b0000000010000      );
	(( 3,0 ), 7 , 0b0010110            );
	(( 3,1 ), 7 , 0b0010100            );
	(( 3,2 ), 8 , 0b00100101           );
	(( 3,3 ), 9 , 0b000111101          );
	(( 3,4 ), 9 , 0b000111000          );
	(( 3,5 ), 10, 0b0001001111         );
	(( 3,6 ), 10, 0b0001001001         );
	(( 3,7 ), 10, 0b0001000000         );
	(( 3,8 ), 10, 0b0000101011         );
	(( 3,9 ), 11, 0b00001001100        );
	(( 3,10), 11, 0b00000111000        );
	(( 3,11), 11, 0b00000100101        );
	(( 3,12), 11, 0b00000011010        );
	(( 3,13), 12, 0b000000011111       );
	(( 3,14), 13, 0b0000000011001      );
	(( 3,15), 13, 0b0000000001110      );
	(( 4,0 ), 8 , 0b00100011           );
	(( 4,1 ), 7 , 0b0010000            );
	(( 4,2 ), 9 , 0b000111100          );
	(( 4,3 ), 9 , 0b000111001          );
	(( 4,4 ), 10, 0b0001100001         );
	(( 4,5 ), 10, 0b0001001011         );
	(( 4,6 ), 11, 0b00001110010        );
	(( 4,7 ), 11, 0b00001011011        );
	(( 4,8 ), 10, 0b0000110110         );
	(( 4,9 ), 11, 0b00001001001        );
	(( 4,10), 11, 0b00000110111        );
	(( 4,11), 12, 0b000000101001       );
	(( 4,12), 12, 0b000000110000       );
	(( 4,13), 13, 0b0000000110101      );
	(( 4,14), 13, 0b0000000010111      );
	(( 4,15), 14, 0b00000000011000     );
	(( 5,0 ), 9 , 0b000111010          );
	(( 5,1 ), 8 , 0b00011011           );
	(( 5,2 ), 9 , 0b000110010          );
	(( 5,3 ), 10, 0b0001100000         );
	(( 5,4 ), 10, 0b0001001100         );
	(( 5,5 ), 10, 0b0001000110         );
	(( 5,6 ), 11, 0b00001011101        );
	(( 5,7 ), 11, 0b00001010100        );
	(( 5,8 ), 11, 0b00001001101        );
	(( 5,9 ), 11, 0b00000111010        );
	(( 5,10), 12, 0b000001001111       );
	(( 5,11), 11, 0b00000011101        );
	(( 5,12), 13, 0b0000001001010      );
	(( 5,13), 13, 0b0000000110001      );
	(( 5,14), 14, 0b00000000101001     );
	(( 5,15), 14, 0b00000000010001     );
	(( 6,0 ), 9 , 0b000101111          );
	(( 6,1 ), 9 , 0b000101101          );
	(( 6,2 ), 10, 0b0001001110         );
	(( 6,3 ), 10, 0b0001001010         );
	(( 6,4 ), 11, 0b00001110011        );
	(( 6,5 ), 11, 0b00001011110        );
	(( 6,6 ), 11, 0b00001011010        );
	(( 6,7 ), 11, 0b00001001111        );
	(( 6,8 ), 11, 0b00001000101        );
	(( 6,9 ), 12, 0b000001010011       );
	(( 6,10), 12, 0b000001000111       );
	(( 6,11), 12, 0b000000110010       );
	(( 6,12), 13, 0b0000000111011      );
	(( 6,13), 13, 0b0000000100110      );
	(( 6,14), 14, 0b00000000100100     );
	(( 6,15), 14, 0b00000000001111     );
	(( 7,0 ), 10, 0b0001001000         );
	(( 7,1 ), 9 , 0b000100010          );
	(( 7,2 ), 10, 0b0000111000         );
	(( 7,3 ), 11, 0b00001011111        );
	(( 7,4 ), 11, 0b00001011100        );
	(( 7,5 ), 11, 0b00001010101        );
	(( 7,6 ), 12, 0b000001011011       );
	(( 7,7 ), 12, 0b000001011010       );
	(( 7,8 ), 12, 0b000001010110       );
	(( 7,9 ), 12, 0b000001001001       );
	(( 7,10), 13, 0b0000001001101      );
	(( 7,11), 13, 0b0000001000001      );
	(( 7,12), 13, 0b0000000110011      );
	(( 7,13), 14, 0b00000000101100     );
	(( 7,14), 16, 0b0000000000101011   );
	(( 7,15), 16, 0b0000000000101010   );
	(( 8,0 ), 9 , 0b000101011          );
	(( 8,1 ), 8 , 0b00010100           );
	(( 8,2 ), 9 , 0b000011110          );
	(( 8,3 ), 10, 0b0000101100         );
	(( 8,4 ), 10, 0b0000110111         );
	(( 8,5 ), 11, 0b00001001110        );
	(( 8,6 ), 11, 0b00001001000        );
	(( 8,7 ), 12, 0b000001010111       );
	(( 8,8 ), 12, 0b000001001110       );
	(( 8,9 ), 12, 0b000000111101       );
	(( 8,10), 12, 0b000000101110       );
	(( 8,11), 13, 0b0000000110110      );
	(( 8,12), 13, 0b0000000100101      );
	(( 8,13), 14, 0b00000000011110     );
	(( 8,14), 15, 0b000000000010100    );
	(( 8,15), 15, 0b000000000010000    );
	(( 9,0 ), 10, 0b0000110101         );
	(( 9,1 ), 9 , 0b000011001          );
	(( 9,2 ), 10, 0b0000101001         );
	(( 9,3 ), 10, 0b0000100101         );
	(( 9,4 ), 11, 0b00000101100        );
	(( 9,5 ), 11, 0b00000111011        );
	(( 9,6 ), 11, 0b00000110110        );
	(( 9,7 ), 13, 0b0000001010001      );
	(( 9,8 ), 12, 0b000001000010       );
	(( 9,9 ), 13, 0b0000001001100      );
	(( 9,10), 13, 0b0000000111001      );
	(( 9,11), 14, 0b00000000110110     );
	(( 9,12), 14, 0b00000000100101     );
	(( 9,13), 14, 0b00000000010010     );
	(( 9,14), 16, 0b0000000000100111   );
	(( 9,15), 15, 0b000000000001011    );
	((10,0 ), 10, 0b0000100011         );
	((10,1 ), 10, 0b0000100001         );
	((10,2 ), 10, 0b0000011111         );
	((10,3 ), 11, 0b00000111001        );
	((10,4 ), 11, 0b00000101010        );
	((10,5 ), 12, 0b000001010010       );
	((10,6 ), 12, 0b000001001000       );
	((10,7 ), 13, 0b0000001010000      );
	((10,8 ), 12, 0b000000101111       );
	((10,9 ), 13, 0b0000000111010      );
	((10,10), 14, 0b00000000110111     );
	((10,11), 13, 0b0000000010101      );
	((10,12), 14, 0b00000000010110     );
	((10,13), 15, 0b000000000011010    );
	((10,14), 16, 0b0000000000100110   );
	((10,15), 17, 0b00000000000010110  );
	((11,0 ), 11, 0b00000110101        );
	((11,1 ), 10, 0b0000011001         );
	((11,2 ), 10, 0b0000010111         );
	((11,3 ), 11, 0b00000100110        );
	((11,4 ), 12, 0b000001000110       );
	((11,5 ), 12, 0b000000111100       );
	((11,6 ), 12, 0b000000110011       );
	((11,7 ), 12, 0b000000100100       );
	((11,8 ), 13, 0b0000000110111      );
	((11,9 ), 13, 0b0000000011010      );
	((11,10), 13, 0b0000000100010      );
	((11,11), 14, 0b00000000010111     );
	((11,12), 15, 0b000000000011011    );
	((11,13), 15, 0b000000000001110    );
	((11,14), 15, 0b000000000001001    );
	((11,15), 16, 0b0000000000000111   );
	((12,0 ), 11, 0b00000100010        );
	((12,1 ), 11, 0b00000100000        );
	((12,2 ), 11, 0b00000011100        );
	((12,3 ), 12, 0b000000100111       );
	((12,4 ), 12, 0b000000110001       );
	((12,5 ), 13, 0b0000001001011      );
	((12,6 ), 12, 0b000000011110       );
	((12,7 ), 13, 0b0000000110100      );
	((12,8 ), 14, 0b00000000110000     );
	((12,9 ), 14, 0b00000000101000     );
	((12,10), 15, 0b000000000110100    );
	((12,11), 15, 0b000000000011100    );
	((12,12), 15, 0b000000000010010    );
	((12,13), 16, 0b0000000000010001   );
	((12,14), 16, 0b0000000000001001   );
	((12,15), 16, 0b0000000000000101   );
	((13,0 ), 12, 0b000000101101       );
	((13,1 ), 11, 0b00000010101        );
	((13,2 ), 12, 0b000000100010       );
	((13,3 ), 13, 0b0000001000000      );
	((13,4 ), 13, 0b0000000111000      );
	((13,5 ), 13, 0b0000000110010      );
	((13,6 ), 14, 0b00000000110001     );
	((13,7 ), 14, 0b00000000101101     );
	((13,8 ), 14, 0b00000000011111     );
	((13,9 ), 14, 0b00000000010011     );
	((13,10), 14, 0b00000000001100     );
	((13,11), 15, 0b000000000001111    );
	((13,12), 16, 0b0000000000001010   );
	((13,13), 15, 0b000000000000111    );
	((13,14), 16, 0b0000000000000110   );
	((13,15), 16, 0b0000000000000011   );
	((14, 0), 13, 0b0000000110000      );
	((14, 1), 12, 0b000000010111       );
	((14, 2), 12, 0b000000010100       );
	((14, 3), 13, 0b0000000100111      );
	((14, 4), 13, 0b0000000100100      );
	((14, 5), 13, 0b0000000100011      );
	((14, 6), 15, 0b000000000110101    );
	((14, 7), 14, 0b00000000010101     );
	((14, 8), 14, 0b00000000010000     );
	((14, 9), 17, 0b00000000000010111  );
	((14,10), 15, 0b000000000001101    );
	((14,11), 15, 0b000000000001010    );
	((14,12), 15, 0b000000000000110    );
	((14,13), 17, 0b00000000000000001  );
	((14,14), 16, 0b0000000000000100   );
	((14,15), 16, 0b0000000000000010   );
	((15, 0), 12, 0b000000010000       );
	((15, 1), 12, 0b000000001111       );
	((15, 2), 13, 0b0000000010001      );
	((15, 3), 14, 0b00000000011011     );
	((15, 4), 14, 0b00000000011001     );
	((15, 5), 14, 0b00000000010100     );
	((15, 6), 15, 0b000000000011101    );
	((15, 7), 14, 0b00000000001011     );
	((15, 8), 15, 0b000000000010001    );
	((15, 9), 15, 0b000000000001100    );
	((15,10), 16, 0b0000000000010000   );
	((15,11), 16, 0b0000000000001000   );
	((15,12), 19, 0b0000000000000000001);
	((15,13), 18, 0b000000000000000001 );
	((15,14), 19, 0b0000000000000000000);
	((15,15), 16, 0b0000000000000001   );
|];;

  No table 14 either ...

let   ht15   =   [|
	(( 0, 0),  3, 0b111          );
	(( 0, 1),  4, 0b1100         );
	(( 0, 2),  5, 0b10010        );
	(( 0, 3),  7, 0b0110101      );
	(( 0, 4),  7, 0b0101111      );
	(( 0, 5),  8, 0b01001100     );
	(( 0, 6),  9, 0b001111100    );
	(( 0, 7),  9, 0b001101100    );
	(( 0, 8),  9, 0b001011001    );
	(( 0, 9), 10, 0b0001111011   );
	(( 0,10), 10, 0b0001101100   );
	(( 0,11), 11, 0b00001110111  );
	(( 0,12), 11, 0b00001101011  );
	(( 0,13), 11, 0b00001010001  );
	(( 0,14), 12, 0b000001111010 );
	(( 0,15), 13, 0b0000000111111);
	(( 1, 0),  4, 0b1101         );
	(( 1, 1),  3, 0b101          );
	(( 1, 2),  5, 0b10000        );
	(( 1, 3),  6, 0b011011       );
	(( 1, 4),  7, 0b0101110      );
	(( 1, 5),  7, 0b0100100      );
	(( 1, 6),  8, 0b00111101     );
	(( 1, 7),  8, 0b00110011     );
	(( 1, 8),  8, 0b00101010     );
	(( 1, 9),  9, 0b001000110    );
	(( 1,10),  9, 0b000110100    );
	(( 1,11), 10, 0b0001010011   );
	(( 1,12), 10, 0b0001000001   );
	(( 1,13), 10, 0b0000101001   );
	(( 1,14), 11, 0b00000111011  );
	(( 1,15), 11, 0b00000100100  );
	(( 2, 0),  5, 0b10011        );
	(( 2, 1),  5, 0b10001        );
	(( 2, 2),  5, 0b01111        );
	(( 2, 3),  6, 0b011000       );
	(( 2, 4),  7, 0b0101001      );
	(( 2, 5),  7, 0b0100010      );
	(( 2, 6),  8, 0b00111011     );
	(( 2, 7),  8, 0b00110000     );
	(( 2, 8),  8, 0b00101000     );
	(( 2, 9),  9, 0b001000000    );
	(( 2,10),  9, 0b000110010    );
	(( 2,11), 10, 0b0001001110   );
	(( 2,12), 10, 0b0000111110   );
	(( 2,13), 11, 0b00001010000  );
	(( 2,14), 11, 0b00000111000  );
	(( 2,15), 11, 0b00000100001  );
	(( 3, 0),  6, 0b011101       );
	(( 3, 1),  6, 0b011100       );
	(( 3, 2),  6, 0b011001       );
	(( 3, 3),  7, 0b0101011      );
	(( 3, 4),  7, 0b0100111      );
	(( 3, 5),  8, 0b00111111     );
	(( 3, 6),  8, 0b00110111     );
	(( 3, 7),  9, 0b001011101    );
	(( 3, 8),  9, 0b001001100    );
	(( 3, 9),  9, 0b000111011    );
	(( 3,10), 10, 0b0001011101   );
	(( 3,11), 10, 0b0001001000   );
	(( 3,12), 10, 0b0000110110   );
	(( 3,13), 11, 0b00001001011  );
	(( 3,14), 11, 0b00000110010  );
	(( 3,15), 11, 0b00000011101  );
	(( 4, 0),  7, 0b0110100      );
	(( 4, 1),  6, 0b010110       );
	(( 4, 2),  7, 0b0101010      );
	(( 4, 3),  7, 0b0101000      );
	(( 4, 4),  8, 0b01000011     );
	(( 4, 5),  8, 0b00111001     );
	(( 4, 6),  9, 0b001011111    );
	(( 4, 7),  9, 0b001001111    );
	(( 4, 8),  9, 0b001001000    );
	(( 4, 9),  9, 0b000111001    );
	(( 4,10), 10, 0b0001011001   );
	(( 4,11), 10, 0b0001000101   );
	(( 4,12), 10, 0b0000110001   );
	(( 4,13), 11, 0b00001000010  );
	(( 4,14), 11, 0b00000101110  );
	(( 4,15), 11, 0b00000011011  );
	(( 5, 0),  8, 0b01001101     );
	(( 5, 1),  7, 0b0100101      );
	(( 5, 2),  7, 0b0100011      );
	(( 5, 3),  8, 0b01000010     );
	(( 5, 4),  8, 0b00111010     );
	(( 5, 5),  8, 0b00110100     );
	(( 5, 6),  9, 0b001011011    );
	(( 5, 7),  9, 0b001001010    );
	(( 5, 8),  9, 0b000111110    );
	(( 5, 9),  9, 0b000110000    );
	(( 5,10), 10, 0b0001001111   );
	(( 5,11), 10, 0b0000111111   );
	(( 5,12), 11, 0b00001011010  );
	(( 5,13), 11, 0b00000111110  );
	(( 5,14), 11, 0b00000101000  );
	(( 5,15), 12, 0b000000100110 );
	(( 6, 0),  9, 0b001111101    );
	(( 6, 1),  7, 0b0100000      );
	(( 6, 2),  8, 0b00111100     );
	(( 6, 3),  8, 0b00111000     );
	(( 6, 4),  8, 0b00110010     );
	(( 6, 5),  9, 0b001011100    );
	(( 6, 6),  9, 0b001001110    );
	(( 6, 7),  9, 0b001000001    );
	(( 6, 8),  9, 0b000110111    );
	(( 6, 9), 10, 0b0001010111   );
	(( 6,10), 10, 0b0001000111   );
	(( 6,11), 10, 0b0000110011   );
	(( 6,12), 11, 0b00001001001  );
	(( 6,13), 11, 0b00000110011  );
	(( 6,14), 12, 0b000001000110 );
	(( 6,15), 12, 0b000000011110 );
	(( 7, 0),  9, 0b001101101    );
	(( 7, 1),  8, 0b00110101     );
	(( 7, 2),  8, 0b00110001     );
	(( 7, 3),  9, 0b001011110    );
	(( 7, 4),  9, 0b001011000    );
	(( 7, 5),  9, 0b001001011    );
	(( 7, 6),  9, 0b001000010    );
	(( 7, 7), 10, 0b0001111010   );
	(( 7, 8), 10, 0b0001011011   );
	(( 7, 9), 10, 0b0001001001   );
	(( 7,10), 10, 0b0000111000   );
	(( 7,11), 10, 0b0000101010   );
	(( 7,12), 11, 0b00001000000  );
	(( 7,13), 11, 0b00000101100  );
	(( 7,14), 11, 0b00000010101  );
	(( 7,15), 12, 0b000000011001 );
	(( 8, 0),  9, 0b001011010    );
	(( 8, 1),  8, 0b00101011     );
	(( 8, 2),  8, 0b00101001     );
	(( 8, 3),  9, 0b001001101    );
	(( 8, 4),  9, 0b001001001    );
	(( 8, 5),  9, 0b000111111    );
	(( 8, 6),  9, 0b000111000    );
	(( 8, 7), 10, 0b0001011100   );
	(( 8, 8), 10, 0b0001001101   );
	(( 8, 9), 10, 0b0001000010   );
	(( 8,10), 10, 0b0000101111   );
	(( 8,11), 11, 0b00001000011  );
	(( 8,12), 11, 0b00000110000  );
	(( 8,13), 12, 0b000000110101 );
	(( 8,14), 12, 0b000000100100 );
	(( 8,15), 12, 0b000000010100 );
	(( 9, 0),  9, 0b001000111    );
	(( 9, 1),  8, 0b00100010     );
	(( 9, 2),  9, 0b001000011    );
	(( 9, 3),  9, 0b000111100    );
	(( 9, 4),  9, 0b000111010    );
	(( 9, 5),  9, 0b000110001    );
	(( 9, 6), 10, 0b0001011000   );
	(( 9, 7), 10, 0b0001001100   );
	(( 9, 8), 10, 0b0001000011   );
	(( 9, 9), 11, 0b00001101010  );
	(( 9,10), 11, 0b00001000111  );
	(( 9,11), 11, 0b00000110110  );
	(( 9,12), 11, 0b00000100110  );
	(( 9,13), 12, 0b000000100111 );
	(( 9,14), 12, 0b000000010111 );
	(( 9,15), 12, 0b000000001111 );
	((10, 0), 10, 0b0001101101   );
	((10, 1),  9, 0b000110101    );
	((10, 2),  9, 0b000110011    );
	((10, 3),  9, 0b000101111    );
	((10, 4), 10, 0b0001011010   );
	((10, 5), 10, 0b0001010010   );
	((10, 6), 10, 0b0000111010   );
	((10, 7), 10, 0b0000111001   );
	((10, 8), 10, 0b0000110000   );
	((10, 9), 11, 0b00001001000  );
	((10,10), 11, 0b00000111001  );
	((10,11), 11, 0b00000101001  );
	((10,12), 11, 0b00000010111  );
	((10,13), 12, 0b000000011011 );
	((10,14), 13, 0b0000000111110);
	((10,15), 12, 0b000000001001 );
	((11, 0), 10, 0b0001010110   );
	((11, 1),  9, 0b000101010    );
	((11, 2),  9, 0b000101000    );
	((11, 3),  9, 0b000100101    );
	((11, 4), 10, 0b0001000110   );
	((11, 5), 10, 0b0001000000   );
	((11, 6), 10, 0b0000110100   );
	((11, 7), 10, 0b0000101011   );
	((11, 8), 11, 0b00001000110  );
	((11, 9), 11, 0b00000110111  );
	((11,10), 11, 0b00000101010  );
	((11,11), 11, 0b00000011001  );
	((11,12), 12, 0b000000011101 );
	((11,13), 12, 0b000000010010 );
	((11,14), 12, 0b000000001011 );
	((11,15), 13, 0b0000000001011);
	((12, 0), 11, 0b00001110110  );
	((12, 1), 10, 0b0001000100   );
	((12, 2),  9, 0b000011110    );
	((12, 3), 10, 0b0000110111   );
	((12, 4), 10, 0b0000110010   );
	((12, 5), 10, 0b0000101110   );
	((12, 6), 11, 0b00001001010  );
	((12, 7), 11, 0b00001000001  );
	((12, 8), 11, 0b00000110001  );
	((12, 9), 11, 0b00000100111  );
	((12,10), 11, 0b00000011000  );
	((12,11), 11, 0b00000010000  );
	((12,12), 12, 0b000000010110 );
	((12,13), 12, 0b000000001101 );
	((12,14), 13, 0b0000000001110);
	((12,15), 13, 0b0000000000111);
	((13, 0), 11, 0b00001011011  );
	((13, 1), 10, 0b0000101100   );
	((13, 2), 10, 0b0000100111   );
	((13, 3), 10, 0b0000100110   );
	((13, 4), 10, 0b0000100010   );
	((13, 5), 11, 0b00000111111  );
	((13, 6), 11, 0b00000110100  );
	((13, 7), 11, 0b00000101101  );
	((13, 8), 11, 0b00000011111  );
	((13, 9), 12, 0b000000110100 );
	((13,10), 12, 0b000000011100 );
	((13,11), 12, 0b000000010011 );
	((13,12), 12, 0b000000001110 );
	((13,13), 12, 0b000000001000 );
	((13,14), 13, 0b0000000001001);
	((13,15), 13, 0b0000000000011);
	((14, 0), 12, 0b000001111011 );
	((14, 1), 11, 0b00000111100  );
	((14, 2), 11, 0b00000111010  );
	((14, 3), 11, 0b00000110101  );
	((14, 4), 11, 0b00000101111  );
	((14, 5), 11, 0b00000101011  );
	((14, 6), 11, 0b00000100000  );
	((14, 7), 11, 0b00000010110  );
	((14, 8), 12, 0b000000100101 );
	((14, 9), 12, 0b000000011000 );
	((14,10), 12, 0b000000010001 );
	((14,11), 12, 0b000000001100 );
	((14,12), 13, 0b0000000001111);
	((14,13), 13, 0b0000000001010);
	((14,14), 12, 0b000000000010 );
	((14,15), 13, 0b0000000000001);
	((15, 0), 12, 0b000001000111 );
	((15, 1), 11, 0b00000100101  );
	((15, 2), 11, 0b00000100010  );
	((15, 3), 11, 0b00000011110  );
	((15, 4), 11, 0b00000011100  );
	((15, 5), 11, 0b00000010100  );
	((15, 6), 11, 0b00000010001  );
	((15, 7), 12, 0b000000011010 );
	((15, 8), 12, 0b000000010101 );
	((15, 9), 12, 0b000000010000 );
	((15,10), 12, 0b000000001010 );
	((15,11), 12, 0b000000000110 );
	((15,12), 13, 0b0000000001000);
	((15,13), 13, 0b0000000000110);
	((15,14), 13, 0b0000000000010);
	((15,15), 13, 0b0000000000000);
|];;

let ht16 = [|
	(( 0, 0),  1,0b1                );
	(( 0, 1),  4,0b0101             );
	(( 0, 2),  6,0b001110           );
	(( 0, 3),  8,0b00101100         );
	(( 0, 4),  9,0b001001010        );
	(( 0, 5),  9,0b000111111        );
	(( 0, 6), 10,0b0001101110       );
	(( 0, 7), 10,0b0001011101       );
	(( 0, 8), 11,0b00010101100      );
	(( 0, 9), 11,0b00010010101      );
	(( 0,10), 11,0b00010001010      );
	(( 0,11), 12,0b000011110010     );
	(( 0,12), 12,0b000011100001     );
	(( 0,13), 12,0b000011000011     );
	(( 0,14), 13,0b0000101111000    );
	(( 0,15),  9,0b000010001        );
	(( 1, 0),  3,0b011              );
	(( 1, 1),  4,0b0100             );
	(( 1, 2),  6,0b001100           );
	(( 1, 3),  7,0b0010100          );
	(( 1, 4),  8,0b00100011         );
	(( 1, 5),  9,0b000111110        );
	(( 1, 6),  9,0b000110101        );
	(( 1, 7),  9,0b000101111        );
	(( 1, 8), 10,0b0001010011       );
	(( 1, 9), 10,0b0001001011       );
	(( 1,10), 10,0b0001000100       );
	(( 1,11), 11,0b00001110111      );
	(( 1,12), 12,0b000011001001     );
	(( 1,13), 11,0b00001101011      );
	(( 1,14), 12,0b000011001111     );
	(( 1,15),  8,0b00001001         );
	(( 2, 0),  6,0b001111           );
	(( 2, 1),  6,0b001101           );
	(( 2, 2),  7,0b0010111          );
	(( 2, 3),  8,0b00100110         );
	(( 2, 4),  9,0b001000011        );
	(( 2, 5),  9,0b000111010        );
	(( 2, 6), 10,0b0001100111       );
	(( 2, 7), 10,0b0001011010       );
	(( 2, 8), 11,0b00010100001      );
	(( 2, 9), 10,0b0001001000       );
	(( 2,10), 11,0b00001111111      );
	(( 2,11), 11,0b00001110101      );
	(( 2,12), 11,0b00001101110      );
	(( 2,13), 12,0b000011010001     );
	(( 2,14), 12,0b000011001110     );
	(( 2,15),  9,0b000010000        );
	(( 3, 0),  8,0b00101101         );
	(( 3, 1),  7,0b0010101          );
	(( 3, 2),  8,0b00100111         );
	(( 3, 3),  9,0b001000101        );
	(( 3, 4),  9,0b001000000        );
	(( 3, 5), 10,0b0001110010       );
	(( 3, 6), 10,0b0001100011       );
	(( 3, 7), 10,0b0001010111       );
	(( 3, 8), 11,0b00010011110      );
	(( 3, 9), 11,0b00010001100      );
	(( 3,10), 12,0b000011111100     );
	(( 3,11), 12,0b000011010100     );
	(( 3,12), 12,0b000011000111     );
	(( 3,13), 13,0b0000110000011    );
	(( 3,14), 13,0b0000101101101    );
	(( 3,15), 10,0b0000011010       );
	(( 4, 0),  9,0b001001011        );
	(( 4, 1),  8,0b00100100         );
	(( 4, 2),  9,0b001000100        );
	(( 4, 3),  9,0b001000001        );
	(( 4, 4), 10,0b0001110011       );
	(( 4, 5), 10,0b0001100101       );
	(( 4, 6), 11,0b00010110011      );
	(( 4, 7), 11,0b00010100100      );
	(( 4, 8), 11,0b00010011011      );
	(( 4, 9), 12,0b000100001000     );
	(( 4,10), 12,0b000011110110     );
	(( 4,11), 12,0b000011100010     );
	(( 4,12), 13,0b0000110001011    );
	(( 4,13), 13,0b0000101111110    );
	(( 4,14), 13,0b0000101101010    );
	(( 4,15),  9,0b000001001        );
	(( 5, 0),  9,0b001000010        );
	(( 5, 1),  8,0b00011110         );
	(( 5, 2),  9,0b000111011        );
	(( 5, 3),  9,0b000111000        );
	(( 5, 4), 10,0b0001100110       );
	(( 5, 5), 11,0b00010111001      );
	(( 5, 6), 11,0b00010101101      );
	(( 5, 7), 12,0b000100001001     );
	(( 5, 8), 11,0b00010001110      );
	(( 5, 9), 12,0b000011111101     );
	(( 5,10), 12,0b000011101000     );
	(( 5,11), 13,0b0000110010000    );
	(( 5,12), 13,0b0000110000100    );
	(( 5,13), 13,0b0000101111010    );
	(( 5,14), 14,0b00000110111101   );
	(( 5,15), 10,0b0000010000       );
	(( 6, 0), 10,0b0001101111       );
	(( 6, 1),  9,0b000110110        );
	(( 6, 2),  9,0b000110100        );
	(( 6, 3), 10,0b0001100100       );
	(( 6, 4), 11,0b00010111000      );
	(( 6, 5), 11,0b00010110010      );
	(( 6, 6), 11,0b00010100000      );
	(( 6, 7), 11,0b00010000101      );
	(( 6, 8), 12,0b000100000001     );
	(( 6, 9), 12,0b000011110100     );
	(( 6,10), 12,0b000011100100     );
	(( 6,11), 12,0b000011011001     );
	(( 6,12), 13,0b0000110000001    );
	(( 6,13), 13,0b0000101101110    );
	(( 6,14), 14,0b00001011001011   );
	(( 6,15), 10,0b0000001010       );
	(( 7, 0), 10,0b0001100010       );
	(( 7, 1),  9,0b000110000        );
	(( 7, 2), 10,0b0001011011       );
	(( 7, 3), 10,0b0001011000       );
	(( 7, 4), 11,0b00010100101      );
	(( 7, 5), 11,0b00010011101      );
	(( 7, 6), 11,0b00010010100      );
	(( 7, 7), 12,0b000100000101     );
	(( 7, 8), 12,0b000011111000     );
	(( 7, 9), 13,0b0000110010111    );
	(( 7,10), 13,0b0000110001101    );
	(( 7,11), 13,0b0000101110100    );
	(( 7,12), 13,0b0000101111100    );
	(( 7,13), 15,0b000001101111001  );
	(( 7,14), 15,0b000001101110100  );
	(( 7,15), 10,0b0000001000       );
	(( 8, 0), 10,0b0001010101       );
	(( 8, 1), 10,0b0001010100       );
	(( 8, 2), 10,0b0001010001       );
	(( 8, 3), 11,0b00010011111      );
	(( 8, 4), 11,0b00010011100      );
	(( 8, 5), 11,0b00010001111      );
	(( 8, 6), 12,0b000100000100     );
	(( 8, 7), 12,0b000011111001     );
	(( 8, 8), 13,0b0000110101011    );
	(( 8, 9), 13,0b0000110010001    );
	(( 8,10), 13,0b0000110001000    );
	(( 8,11), 13,0b0000101111111    );
	(( 8,12), 14,0b00001011010111   );
	(( 8,13), 14,0b00001011001001   );
	(( 8,14), 14,0b00001011000100   );
	(( 8,15), 10,0b0000000111       );
	(( 9, 0), 11,0b00010011010      );
	(( 9, 1), 10,0b0001001100       );
	(( 9, 2), 10,0b0001001001       );
	(( 9, 3), 11,0b00010001101      );
	(( 9, 4), 11,0b00010000011      );
	(( 9, 5), 12,0b000100000000     );
	(( 9, 6), 12,0b000011110101     );
	(( 9, 7), 13,0b0000110101010    );
	(( 9, 8), 13,0b0000110010110    );
	(( 9, 9), 13,0b0000110001010    );
	(( 9,10), 13,0b0000110000000    );
	(( 9,11), 14,0b00001011011111   );
	(( 9,12), 13,0b0000101100111    );
	(( 9,13), 14,0b00001011000110   );
	(( 9,14), 13,0b0000101100000    );
	(( 9,15), 11,0b00000001011      );
	((10, 0), 11,0b00010001011      );
	((10, 1), 11,0b00010000001      );
	((10, 2), 10,0b0001000011       );
	((10, 3), 11,0b00001111101      );
	((10, 4), 12,0b000011110111     );
	((10, 5), 12,0b000011101001     );
	((10, 6), 12,0b000011100101     );
	((10, 7), 12,0b000011011011     );
	((10, 8), 13,0b0000110001001    );
	((10, 9), 14,0b00001011100111   );
	((10,10), 14,0b00001011100001   );
	((10,11), 14,0b00001011010000   );
	((10,12), 15,0b000001101110101  );
	((10,13), 15,0b000001101110010  );
	((10,14), 14,0b00000110110111   );
	((10,15), 10,0b0000000100       );
	((11, 0), 12,0b000011110011     );
	((11, 1), 11,0b00001111000      );
	((11, 2), 11,0b00001110110      );
	((11, 3), 11,0b00001110011      );
	((11, 4), 12,0b000011100011     );
	((11, 5), 12,0b000011011111     );
	((11, 6), 13,0b0000110001100    );
	((11, 7), 14,0b00001011101010   );
	((11, 8), 14,0b00001011100110   );
	((11, 9), 14,0b00001011100000   );
	((11,10), 14,0b00001011010001   );
	((11,11), 14,0b00001011001000   );
	((11,12), 14,0b00001011000010   );
	((11,13), 13,0b0000011011111    );
	((11,14), 14,0b00000110110100   );
	((11,15), 11,0b00000000110      );
	((12, 0), 12,0b000011001010     );
	((12, 1), 12,0b000011100000     );
	((12, 2), 12,0b000011011110     );
	((12, 3), 12,0b000011011010     );
	((12, 4), 12,0b000011011000     );
	((12, 5), 13,0b0000110000101    );
	((12, 6), 13,0b0000110000010    );
	((12, 7), 13,0b0000101111101    );
	((12, 8), 13,0b0000101101100    );
	((12, 9), 15,0b000001101111000  );
	((12,10), 14,0b00000110111011   );
	((12,11), 14,0b00001011000011   );
	((12,12), 14,0b00000110111000   );
	((12,13), 14,0b00000110110101   );
	((12,14), 16,0b0000011011000000 );
	((12,15), 11,0b00000000100      );
	((13, 0), 14,0b00001011101011   );
	((13, 1), 12,0b000011010011     );
	((13, 2), 12,0b000011010010     );
	((13, 3), 12,0b000011010000     );
	((13, 4), 13,0b0000101110010    );
	((13, 5), 13,0b0000101111011    );
	((13, 6), 14,0b00001011011110   );
	((13, 7), 14,0b00001011010011   );
	((13, 8), 14,0b00001011001010   );
	((13, 9), 16,0b0000011011000111 );
	((13,10), 15,0b000001101110011  );
	((13,11), 15,0b000001101101101  );
	((13,12), 15,0b000001101101100  );
	((13,13), 17,0b00000110110000011);
	((13,14), 15,0b000001101100001  );
	((13,15), 11,0b00000000010      );
	((14, 0), 13,0b0000101111001    );
	((14, 1), 13,0b0000101110001    );
	((14, 2), 11,0b00001100110      );
	((14, 3), 12,0b000010111011     );
	((14, 4), 14,0b00001011010110   );
	((14, 5), 14,0b00001011010010   );
	((14, 6), 13,0b0000101100110    );
	((14, 7), 14,0b00001011000111   );
	((14, 8), 14,0b00001011000101   );
	((14, 9), 15,0b000001101100010  );
	((14,10), 16,0b0000011011000110 );
	((14,11), 15,0b000001101100111  );
	((14,12), 17,0b00000110110000010);
	((14,13), 15,0b000001101100110  );
	((14,14), 14,0b00000110110010   );
	((14,15), 11,0b00000000000      );
	((15, 0),  9,0b000001100        );
	((15, 1),  8,0b00001010         );
	((15, 2),  8,0b00000111         );
	((15, 3),  9,0b000001011        );
	((15, 4),  9,0b000001010        );
	((15, 5), 10,0b0000010001       );
	((15, 6), 10,0b0000001011       );
	((15, 7), 10,0b0000001001       );
	((15, 8), 11,0b00000001101      );
	((15, 9), 11,0b00000001100      );
	((15,10), 11,0b00000001010      );
	((15,11), 11,0b00000000111      );
	((15,12), 11,0b00000000101      );
	((15,13), 11,0b00000000011      );
	((15,14), 11,0b00000000001      );
	((15,15),  8,0b00000011         );
|];;

let ht17 = ht16;;
let ht18 = ht16;;
let ht19 = ht16;;
let ht20 = ht16;;
let ht21 = ht16;;
let ht22 = ht16;;
let ht23 = ht16;;

let   ht24   =   [|
	(( 0, 0),  4, 0b1111        );
	(( 0, 1),  4, 0b1101        );
	(( 0, 2),  6, 0b101110      );
	(( 0, 3),  7, 0b1010000     );
	(( 0, 4),  8, 0b10010010    );
	(( 0, 5),  9, 0b100000110   );
	(( 0, 6),  9, 0b011111000   );
	(( 0, 7), 10, 0b0110110010  );
	(( 0, 8), 10, 0b0110101010  );
	(( 0, 9), 11, 0b01010011101 );
	(( 0,10), 11, 0b01010001101 );
	(( 0,11), 11, 0b01010001001 );
	(( 0,12), 11, 0b01001101101 );
	(( 0,13), 11, 0b01000000101 );
	(( 0,14), 12, 0b010000001000);
	(( 0,15),  9, 0b001011000   );
	(( 1, 0),  4, 0b1110        );
	(( 1, 1),  4, 0b1100        );
	(( 1, 2),  5, 0b10101       );
	(( 1, 3),  6, 0b100110      );
	(( 1, 4),  7, 0b1000111     );
	(( 1, 5),  8, 0b10000010    );
	(( 1, 6),  8, 0b01111010    );
	(( 1, 7),  9, 0b011011000   );
	(( 1, 8),  9, 0b011010001   );
	(( 1, 9),  9, 0b011000110   );
	(( 1,10), 10, 0b0101000111  );
	(( 1,11), 10, 0b0101011001  );
	(( 1,12), 10, 0b0100111111  );
	(( 1,13), 10, 0b0100101001  );
	(( 1,14), 10, 0b0100010111  );
	(( 1,15),  8, 0b00101010    );
	(( 2, 0),  6, 0b101111      );
	(( 2, 1),  5, 0b10110       );
	(( 2, 2),  6, 0b101001      );
	(( 2, 3),  7, 0b1001010     );
	(( 2, 4),  7, 0b1000100     );
	(( 2, 5),  8, 0b10000000    );
	(( 2, 6),  8, 0b01111000    );
	(( 2, 7),  9, 0b011011101   );
	(( 2, 8),  9, 0b011001111   );
	(( 2, 9),  9, 0b011000010   );
	(( 2,10),  9, 0b010110110   );
	(( 2,11), 10, 0b0101010100  );
	(( 2,12), 10, 0b0100111011  );
	(( 2,13), 10, 0b0100100111  );
	(( 2,14), 11, 0b01000011101 );
	(( 2,15),  7, 0b0010010     );
	(( 3, 0),  7, 0b1010001     );
	(( 3, 1),  6, 0b100111      );
	(( 3, 2),  7, 0b1001011     );
	(( 3, 3),  7, 0b1000110     );
	(( 3, 4),  8, 0b10000110    );
	(( 3, 5),  8, 0b01111101    );
	(( 3, 6),  8, 0b01110100    );
	(( 3, 7),  9, 0b011011100   );
	(( 3, 8),  9, 0b011001100   );
	(( 3, 9),  9, 0b010111110   );
	(( 3,10),  9, 0b010110010   );
	(( 3,11), 10, 0b0101000101  );
	(( 3,12), 10, 0b0100110111  );
	(( 3,13), 10, 0b0100100101  );
	(( 3,14), 10, 0b0100001111  );
	(( 3,15),  7, 0b0010000     );
	(( 4, 0),  8, 0b10010011    );
	(( 4, 1),  7, 0b1001000     );
	(( 4, 2),  7, 0b1000101     );
	(( 4, 3),  8, 0b10000111    );
	(( 4, 4),  8, 0b01111111    );
	(( 4, 5),  8, 0b01110110    );
	(( 4, 6),  8, 0b01110000    );
	(( 4, 7),  9, 0b011010010   );
	(( 4, 8),  9, 0b011001000   );
	(( 4, 9),  9, 0b010111100   );
	(( 4,10), 10, 0b0101100000  );
	(( 4,11), 10, 0b0101000011  );
	(( 4,12), 10, 0b0100110010  );
	(( 4,13), 10, 0b0100011101  );
	(( 4,14), 11, 0b01000011100 );
	(( 4,15),  7, 0b0001110     );
	(( 5, 0),  9, 0b100000111   );
	(( 5, 1),  7, 0b1000010     );
	(( 5, 2),  8, 0b10000001    );
	(( 5, 3),  8, 0b01111110    );
	(( 5, 4),  8, 0b01110111    );
	(( 5, 5),  8, 0b01110010    );
	(( 5, 6),  9, 0b011010110   );
	(( 5, 7),  9, 0b011001010   );
	(( 5, 8),  9, 0b011000000   );
	(( 5, 9),  9, 0b010110100   );
	(( 5,10), 10, 0b0101010101  );
	(( 5,11), 10, 0b0100111101  );
	(( 5,12), 10, 0b0100101101  );
	(( 5,13), 10, 0b0100011001  );
	(( 5,14), 10, 0b0100000110  );
	(( 5,15),  7, 0b0001100     );
	(( 6, 0),  9, 0b011111001   );
	(( 6, 1),  8, 0b01111011    );
	(( 6, 2),  8, 0b01111001    );
	(( 6, 3),  8, 0b01110101    );
	(( 6, 4),  8, 0b01110001    );
	(( 6, 5),  9, 0b011010111   );
	(( 6, 6),  9, 0b011001110   );
	(( 6, 7),  9, 0b011000011   );
	(( 6, 8),  9, 0b010111001   );
	(( 6, 9), 10, 0b0101011011  );
	(( 6,10), 10, 0b0101001010  );
	(( 6,11), 10, 0b0100110100  );
	(( 6,12), 10, 0b0100100011  );
	(( 6,13), 10, 0b0100010000  );
	(( 6,14), 11, 0b01000001000 );
	(( 6,15),  7, 0b0001010     );
	(( 7, 0), 10, 0b0110110011  );
	(( 7, 1),  8, 0b01110011    );
	(( 7, 2),  8, 0b01101111    );
	(( 7, 3),  8, 0b01101101    );
	(( 7, 4),  9, 0b011010011   );
	(( 7, 5),  9, 0b011001011   );
	(( 7, 6),  9, 0b011000100   );
	(( 7, 7),  9, 0b010111011   );
	(( 7, 8), 10, 0b0101100001  );
	(( 7, 9), 10, 0b0101001100  );
	(( 7,10), 10, 0b0100111001  );
	(( 7,11), 10, 0b0100101010  );
	(( 7,12), 10, 0b0100011011  );
	(( 7,13), 11, 0b01000010011 );
	(( 7,14), 11, 0b00101111101 );
	(( 7,15),  8, 0b00010001    );
	(( 8, 0), 10, 0b0110101011  );
	(( 8, 1),  9, 0b011010100   );
	(( 8, 2),  9, 0b011010000   );
	(( 8, 3),  9, 0b011001101   );
	(( 8, 4),  9, 0b011001001   );
	(( 8, 5),  9, 0b011000001   );
	(( 8, 6),  9, 0b010111010   );
	(( 8, 7),  9, 0b010110001   );
	(( 8, 8),  9, 0b010101001   );
	(( 8, 9), 10, 0b0101000000  );
	(( 8,10), 10, 0b0100101111  );
	(( 8,11), 10, 0b0100011110  );
	(( 8,12), 10, 0b0100001100  );
	(( 8,13), 11, 0b01000000010 );
	(( 8,14), 11, 0b00101111001 );
	(( 8,15),  8, 0b00010000    );
	(( 9, 0), 10, 0b0101001111  );
	(( 9, 1),  9, 0b011000111   );
	(( 9, 2),  9, 0b011000101   );
	(( 9, 3),  9, 0b010111111   );
	(( 9, 4),  9, 0b010111101   );
	(( 9, 5),  9, 0b010110101   );
	(( 9, 6),  9, 0b010101110   );
	(( 9, 7), 10, 0b0101001101  );
	(( 9, 8), 10, 0b0101000001  );
	(( 9, 9), 10, 0b0100110001  );
	(( 9,10), 10, 0b0100100001  );
	(( 9,11), 10, 0b0100010011  );
	(( 9,12), 11, 0b01000001001 );
	(( 9,13), 11, 0b00101111011 );
	(( 9,14), 11, 0b00101110011 );
	(( 9,15),  8, 0b00001011    );
	((10, 0), 11, 0b01010011100 );
	((10, 1),  9, 0b010111000   );
	((10, 2),  9, 0b010110111   );
	((10, 3),  9, 0b010110011   );
	((10, 4),  9, 0b010101111   );
	((10, 5), 10, 0b0101011000  );
	((10, 6), 10, 0b0101001011  );
	((10, 7), 10, 0b0100111010  );
	((10, 8), 10, 0b0100110000  );
	((10, 9), 10, 0b0100100010  );
	((10,10), 10, 0b0100010101  );
	((10,11), 11, 0b01000010010 );
	((10,12), 11, 0b00101111111 );
	((10,13), 11, 0b00101110101 );
	((10,14), 11, 0b00101101110 );
	((10,15),  8, 0b00001010    );
	((11, 0), 11, 0b01010001100 );
	((11, 1), 10, 0b0101011010  );
	((11, 2),  9, 0b010101011   );
	((11, 3),  9, 0b010101000   );
	((11, 4),  9, 0b010100100   );
	((11, 5), 10, 0b0100111110  );
	((11, 6), 10, 0b0100110101  );
	((11, 7), 10, 0b0100101011  );
	((11, 8), 10, 0b0100011111  );
	((11, 9), 10, 0b0100010100  );
	((11,10), 10, 0b0100000111  );
	((11,11), 11, 0b01000000001 );
	((11,12), 11, 0b00101110111 );
	((11,13), 11, 0b00101110000 );
	((11,14), 11, 0b00101101010 );
	((11,15),  8, 0b00000110    );
	((12, 0), 11, 0b01010001000 );
	((12, 1), 10, 0b0101000010  );
	((12, 2), 10, 0b0100111100  );
	((12, 3), 10, 0b0100111000  );
	((12, 4), 10, 0b0100110011  );
	((12, 5), 10, 0b0100101110  );
	((12, 6), 10, 0b0100100100  );
	((12, 7), 10, 0b0100011100  );
	((12, 8), 10, 0b0100001101  );
	((12, 9), 10, 0b0100000101  );
	((12,10), 11, 0b01000000000 );
	((12,11), 11, 0b00101111000 );
	((12,12), 11, 0b00101110010 );
	((12,13), 11, 0b00101101100 );
	((12,14), 11, 0b00101100111 );
	((12,15),  8, 0b00000100    );
	((13, 0), 11, 0b01001101100 );
	((13, 1), 10, 0b0100101100  );
	((13, 2), 10, 0b0100101000  );
	((13, 3), 10, 0b0100100110  );
	((13, 4), 10, 0b0100100000  );
	((13, 5), 10, 0b0100011010  );
	((13, 6), 10, 0b0100010001  );
	((13, 7), 10, 0b0100001010  );
	((13, 8), 11, 0b01000000011 );
	((13, 9), 11, 0b00101111100 );
	((13,10), 11, 0b00101110110 );
	((13,11), 11, 0b00101110001 );
	((13,12), 11, 0b00101101101 );
	((13,13), 11, 0b00101101001 );
	((13,14), 11, 0b00101100101 );
	((13,15),  8, 0b00000010    );
	((14, 0), 12, 0b010000001001);
	((14, 1), 10, 0b0100011000  );
	((14, 2), 10, 0b0100010110  );
	((14, 3), 10, 0b0100010010  );
	((14, 4), 10, 0b0100001011  );
	((14, 5), 10, 0b0100001000  );
	((14, 6), 10, 0b0100000011  );
	((14, 7), 11, 0b00101111110 );
	((14, 8), 11, 0b00101111010 );
	((14, 9), 11, 0b00101110100 );
	((14,10), 11, 0b00101101111 );
	((14,11), 11, 0b00101101011 );
	((14,12), 11, 0b00101101000 );
	((14,13), 11, 0b00101100110 );
	((14,14), 11, 0b00101100100 );
	((14,15),  8, 0b00000000    );
	((15, 0),  8, 0b00101011    );
	((15, 1),  7, 0b0010100     );
	((15, 2),  7, 0b0010011     );
	((15, 3),  7, 0b0010001     );
	((15, 4),  7, 0b0001111     );
	((15, 5),  7, 0b0001101     );
	((15, 6),  7, 0b0001011     );
	((15, 7),  7, 0b0001001     );
	((15, 8),  7, 0b0000111     );
	((15, 9),  7, 0b0000110     );
	((15,10),  7, 0b0000100     );
	((15,11),  8, 0b00000111    );
	((15,12),  8, 0b00000101    );
	((15,13),  8, 0b00000011    );
	((15,14),  8, 0b00000001    );
	((15,15),  4, 0b0011        );
|];;

let ht25 = ht24;;
let ht26 = ht24;;
let ht27 = ht24;;
let ht28 = ht24;;
let ht29 = ht24;;
let ht30 = ht24;;
let ht31 = ht24;;


let htA = [|
	((0,0,0,0), 1, 0b1     );
	((0,0,0,1), 4, 0b0101  );
	((0,0,1,0), 4, 0b0100  );
	((0,0,1,1), 5, 0b00101 );
	((0,1,0,0), 4, 0b0110  );
	((0,1,0,1), 6, 0b000101);
	((0,1,1,0), 5, 0b00100 );
	((0,1,1,1), 6, 0b000100);
	((1,0,0,0), 4, 0b0111  );
	((1,0,0,1), 5, 0b00011 );
	((1,0,1,0), 5, 0b00110 );
	((1,0,1,1), 6, 0b000000);
	((1,1,0,0), 5, 0b00111 );
	((1,1,0,1), 6, 0b000010);
	((1,1,1,0), 6, 0b000011);
	((1,1,1,1), 6, 0b000001);
|];;
let htB = [|
	((0,0,0,0), 4, 0b1111);
	((0,0,0,1), 4, 0b1110);
	((0,0,1,0), 4, 0b1101);
	((0,0,1,1), 4, 0b1100);
	((0,1,0,0), 4, 0b1011);
	((0,1,0,1), 4, 0b1010);
	((0,1,1,0), 4, 0b1001);
	((0,1,1,1), 4, 0b1000);
	((1,0,0,0), 4, 0b0111);
	((1,0,0,1), 4, 0b0110);
	((1,0,1,0), 4, 0b0101);
	((1,0,1,1), 4, 0b0100);
	((1,1,0,0), 4, 0b0011);
	((1,1,0,1), 4, 0b0010);
	((1,1,1,0), 4, 0b0001);
	((1,1,1,1), 4, 0b0000);
|]


 let make_huffman_tree ht len = 
	 if ht = [ || ] then ( 
		 [ || ] 
	 ) else ( 
		 let array_len = 1 lsl len in 
		 let out_array = Array.make array_len Zero in 

		 let rec find_spot current_out value orig_bits bits index = ( 
			 if bits < = len then ( 
				 ( * Spam up this level
let make_huffman_tree ht len =
	if ht = [||] then (
		[||]
	) else (
		let array_len = 1 lsl len in
		let out_array = Array.make array_len Zero in

		let rec find_spot current_out value orig_bits bits index = (
			if bits <= len then (
				let pad_bits = len - bits in
				let base = index lsl pad_bits in
				for add = 0 to (1 lsl pad_bits) - 1 do
					current_out.(base + add) <- One (value, pad_bits)
				done;
			) else (
				let extra_bits = bits - len in
				let current_index = index lsr extra_bits in
				match current_out.(current_index) with
				| Zero -> (
					let new_out = Array.make array_len Zero in
					let new_index = (index lxor (current_index lsl extra_bits)) in
					find_spot new_out value orig_bits extra_bits new_index;
					current_out.(current_index) <- Many new_out
				)
				| One _ -> (
					raise (Failure "Huffman table specification incorrect")
				)
				| Many new_out -> (
					let new_index = (index lxor (current_index lsl extra_bits)) in
					find_spot new_out value orig_bits extra_bits new_index;
				)
			)
		) in

		Array.iter (fun (value, bits, index) ->
			find_spot out_array value bits bits index
		) ht;

		let rec convert_to_onemany = function
			| Zero -> raise (Failure "Huffman table incomplete")
			| One x -> Single x
			| Many y -> Multiple (Array.map convert_to_onemany y)
		in

		Array.map convert_to_onemany out_array
	)
;;
*)

This is the safe version of the huffman_decode function . It is not useful because there is no MP3 Huffman table with > 30 bits per word

 let huffman_decode_safe ( r_str , r_at ) ht bits = 
	 let rec search_table ( r_str_now , r_at_now ) ht_now = ( 
		 let ( first_bits , ( r_str2 , r_at2 ) ) = read_bits_overflow ( r_str_now , r_at_now ) bits in 
		 match ht_now.(first_bits ) with 
		 | Single ( x , bits ) - > ( 
			 ( x , ( r_str2 , r_at2 - bits ) ) 
		 ) 
		 | Multiple ht_new - > ( 
			 search_table ( r_str2 , r_at2 ) ht_new 
		 ) 
	 ) in 
	 search_table ( r_str , r_at ) ht 
 ; ; 

let huffman_decode_safe (r_str, r_at) ht bits =
	let rec search_table (r_str_now, r_at_now) ht_now = (
		let (first_bits, (r_str2, r_at2)) = read_bits_overflow (r_str_now, r_at_now) bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			(x, (r_str2, r_at2 - bits))
		)
		| Multiple ht_new -> (
			search_table (r_str2, r_at2) ht_new
		)
	) in
	search_table (r_str, r_at) ht
;;
*)


 let huffman_decode ( r_str , r_at ) ht bits = 

	 let rec search_table ( r_str_now , r_at_now ) ht_now = ( 
		 let ( first_bits , ( r_str2 , r_at2 ) ) = read_bits_overflow_unsafe ( r_str_now , r_at_now ) bits in 
		 match ht_now.(first_bits ) with 
		 | Single ( x , bits ) - > ( 
			 ( * This one 's it !
let huffman_decode (r_str, r_at) ht bits =

	let rec search_table (r_str_now, r_at_now) ht_now = (
		let (first_bits, (r_str2, r_at2)) = read_bits_overflow_unsafe (r_str_now, r_at_now) bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			(x, (r_str2, r_at2 - bits))
		)
		| Multiple ht_new -> (
			search_table (r_str2, r_at2) ht_new
		)
	) in
	search_table (r_str, r_at) ht
;;

let huffman_decode_ptrref s ht bits =
	let rec search_table ht_now =
		let first_bits = Ptr.Ref.get_seq_fast_overflow s bits in
		match ht_now.(first_bits) with
		| Single (x, bits) -> (
			 Printf.printf " Bits is % d ( backing up to % d in byte % d , fast is before byte % d)\n " bits ( s. Ptr . Ref.seq_at - bits ) ( ( s. Ptr . Ref.seq_at - bits ) lsr 3 ) s. Ptr . Ref.seq_get_fast_next_byte ;
			Ptr.Ref.set_seq s (s.Ptr.Ref.seq_at - bits);
			x
		)
		| Multiple ht_new -> search_table ht_new
	in
	search_table ht
;;
*)


let global_ht_bits = 8 ; ;
let global_ht = Array.map ( fun x - > make_huffman_tree x global_ht_bits ) [ | ht0 ; ht1 ; ht2 ;  ; ( *
let global_ht_linbits = [| 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;2;3;4;6;8;10;13;4;5;6;7;8;9;11;13 |];;

let global_ht_count1_bits = 6 ; ;

let rec min_max_bits bits_so_far = function
	| Single (_, bits_left_over) -> (bits_so_far - bits_left_over, bits_so_far - bits_left_over)
	| Multiple things -> Array.fold_left (fun (min_so_far,max_so_far) next ->
		let (next_min,next_max) = min_max_bits (bits_so_far + global_ht_bits) next in
		(min min_so_far next_min, max max_so_far next_max)
	) (max_int,min_int) things
;;
let rec handle_tree spaces bits_so_far = function
	| Single ((x,y), leftover) -> Printf.printf "%s%2d:(%d,%d)\n" spaces (bits_so_far - leftover - 1) x y
	| Multiple things -> (
		let next_spaces = spaces ^ "  " in
		Array.iteri (fun num thing ->
			let (min_bits, max_bits) = min_max_bits bits_so_far thing in
			Printf.printf "%s%d (%d~%d):\n" spaces num min_bits max_bits;
			handle_tree next_spaces (bits_so_far + global_ht_bits) thing
		) things
	)
;;
handle_tree "" global_ht_bits (Multiple global_ht.(2));;
exit 4;;
**)
  First build the binary tables
type 'a bin_tree_t = BinLeaf of 'a | BinBranch of 'a bin_tree_t * 'a bin_tree_t;;
let rec make_binary_tree num_bits_now prepend hl =
	let rec find_one = function
		| [] -> None
		| (v, bits, code) :: tl when bits = num_bits_now && code = prepend -> Some v
		| hd :: tl -> find_one tl
	in
	match find_one hl with
	| Some v -> BinLeaf v
	| None -> (
		let path_0 = make_binary_tree (succ num_bits_now) (2 * prepend + 0) hl in
		let path_1 = make_binary_tree (succ num_bits_now) (2 * prepend + 1) hl in
		BinBranch (path_0, path_1)
	)
;;

type 'a flat_tree_t = FlatLeaf of 'a | FlatArray of int * 'a flat_tree_t array | FlatBinary of 'a flat_tree_t * 'a flat_tree_t;;

let rec get_binary_min_max = function
	| BinLeaf _ -> (0,0)
	| BinBranch (path_0, path_1) -> (
		let (min_0, max_0) = get_binary_min_max path_0 in
		let (min_1, max_1) = get_binary_min_max path_1 in
		(1 + min min_0 min_1, 1 + max max_0 max_1)
	)
;;

let rec make_flat_tree = function
	| BinLeaf v -> FlatLeaf (v,0)
	| (BinBranch (path_0, path_1) as n) -> (
		let (min_path, max_path) = get_binary_min_max n in
		let rec flat_of_binary = function
			| BinLeaf x -> FlatLeaf (x,0)
			| BinBranch (x,y) -> FlatBinary (flat_of_binary x, flat_of_binary y)
		in
		if min_path = max_path && min_path > 1 then (
			let rec get_val i num_bits = function
				| BinLeaf v -> FlatLeaf (v,0)
				| BinBranch (path_0, path_1) when num_bits = 0 -> FlatBinary (flat_of_binary path_0, flat_of_binary path_1)
				| BinBranch (path_0, path_1) -> (
					let get_bit = 1 lsl (num_bits - 1) in
					get_val (i land (get_bit - 1)) (pred num_bits) (if i land get_bit <> 0 then path_1 else path_0)
				)
			in
			let flat_array = Array.make (1 lsl min_path) (get_val 0 min_path n) in
			FlatArray (min_path, flat_array)
		) else (
			FlatBinary (make_flat_tree path_0, make_flat_tree path_1)
		)
	)
;;


let rec print_binary_tree spaces = function
	| BinLeaf (x,y) -> Printf.printf "%s(%2d,%2d)\n" spaces x y
	| BinBranch (path_0, path_1) -> (
		let next_spaces = spaces ^ "  " in
		let (min_0, max_0) = get_binary_min_max path_0 in
		Printf.printf "%s0: (%d~%d)\n" spaces min_0 max_0;
		print_binary_tree next_spaces path_0;
		let (min_1, max_1) = get_binary_min_max path_1 in
		Printf.printf "%s1: (%d~%d)\n" spaces min_1 max_1;
		print_binary_tree next_spaces path_1;
	)
;;

  This return the min and  number of bits to EITHER a leaf OR an array
let rec get_flat_min_max = function
	| FlatLeaf _ -> (0,0)
	| FlatArray _ -> (0,0)
	| FlatBinary (path_0, path_1) -> (
		let (min_0, max_0) = get_flat_min_max path_0 in
		let (min_1, max_1) = get_flat_min_max path_1 in
		(1 + min min_0 min_1, 1 + max max_0 max_1)
	)
;;
let rec print_flat_tree spaces = function
	| FlatLeaf ((x,y),back) -> Printf.printf "%s(%2d,%2d) back %d\n" spaces x y back
	| FlatBinary (path_0, path_1) -> (
		let next_spaces = spaces ^ "  " in
		let (min_0, max_0) = get_flat_min_max path_0 in
		Printf.printf "%s0: (%d~%d)\n" spaces min_0 max_0;
		print_flat_tree next_spaces path_0;
		let (min_1, max_1) = get_flat_min_max path_1 in
		Printf.printf "%s1: (%d~%d)\n" spaces min_1 max_1;
		print_flat_tree next_spaces path_1;
	)
	| FlatArray (bits, a) -> (
		Printf.printf "%sARRAY with %d bits:\n" spaces bits;
		let index_spaces = spaces ^ "  " in
		let rec_spaces = index_spaces ^ "  " in
		Array.iteri (fun i x ->
			Printf.printf "%s[%3d]:\n" index_spaces i;
			print_flat_tree rec_spaces x
		) a
	)
;;
print_flat_tree "" (make_flat_tree global_ht_binary_trees.(31));;

Array.iteri (fun i bt ->
	Printf.printf "### %d ###\n" i;
	print_binary_tree "  " bt;
) global_ht_binary_trees;;
exit 4;;
**)

  Note that the default is ( 0,1 ) , which is impossible .
let make_4bit_huffman_encode_table ht =
	let out_table = Array.make 256 (0,0b1) in
	Array.iter (fun ((x,y), l, q) -> out_table.((x lsl 4) lor (y land 15)) <- (l,q)) ht;
	out_table
;;

let make_1bit_huffman_encode_table ht =
	let out_table = Array.make 16 (0,0b1) in
	Array.iter (fun ((v,w,x,y), l, q) -> out_table.(v lsl 3 lor w lsl 2 lor x lsl 1 lor y) <- (l,q)) ht;
	out_table
;;

let global_ht_encode = Array.map ( fun x - > make_huffman_encode_table x ) [ | ht0 ; ht1 ; ht2 ;  ; ( *
let global_ht_encode_count1 = Array.map (fun x -> make_1bit_huffman_encode_table x) [| htA; htB |];;



let quant_bits = Array.mapi (fun t ht ->
	Array.init 256 (fun x -> match ht.(x) with
		| (0,1) -> too_many_bits
		| (b,_) -> (
			let linbits = (if x land 0x0F = 0x0F then global_ht_linbits.(t) else 0) + (if x land 0xF0 = 0xF0 then global_ht_linbits.(t) else 0) in
			b + linbits
		)
	)
) global_ht_encode;;
let quant_bits_count1 = Array.map (fun ht ->
	Array.init 16 (fun x -> fst ht.(x))
) global_ht_encode_count1;;


  I think it would be better to swap the indexes , so the " first " index is the quantizer value and the " last " is the table
let quant_bits_ptr = Ptr.make_page (256 * 32 * 4);;
let quant_bits_ptr16 = Ptr.make_page (256 * 32 * 2);;
for tn = 0 to 32 - 1 do
	let t_now = quant_bits.(tn) in
	for qn = 0 to 256 - 1 do
		let q_now = t_now.(qn) in
		let q_offset = 4 * (qn * 32 + tn) in
		Ptr.put_32_of_int quant_bits_ptr q_offset q_now;
		let q_offset16 = 2 * (qn * 32 + tn) in
		Ptr.put_16_of_int quant_bits_ptr16 q_offset16 q_now;
	done
done;;

let quant_bits_count1_char_ptr = Ptr.make (16 * Array.length quant_bits_count1) 32;;
Array.iteri (fun tn t_now ->
	Array.iteri (fun qn q_now ->
		let q_offset = (qn * 2 + tn) in
		Ptr.put_8_of_int quant_bits_count1_char_ptr q_offset q_now
	) t_now
) quant_bits_count1;;












external write_big_quants_test : int - > int - > int - > Ptr.t - > int - > int = " write_big_quants_test " ; ;

external write_big_to_frame : Ptr.t -> int -> int -> int -> Ptr.t -> int -> int = "mfh_write_big_to_frame_bytecode" "mfh_write_big_to_frame";;

external write_all_to_frame : Ptr.t -> int -> int -> int -> int -> int -> int -> bool -> Ptr.t -> int -> int = "mfh_write_all_to_frame_bytecode" "mfh_write_all_to_frame";;


external flni_test : Ptr.t -> int = "flni_test";;

