diff --git a/README.md b/README.md
index 35a4c6e..56ce7e8 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
 KMC
 =
+[![GitHub downloads](https://img.shields.io/github/downloads/refresh-bio/kmc/total.svg?style=flag&label=GitHub%20downloads)](https://github.com/refresh-bio/KMC/releases)
+[![Bioconda downloads](https://img.shields.io/conda/dn/bioconda/kmc.svg?style=flag&label=Bioconda%20downloads)](https://anaconda.org/bioconda/kmc)
+
 KMC is a disk-based programm for counting k-mers from (possibly gzipped) FASTQ/FASTA files.
 The homepage of the KMC project is http://sun.aei.polsl.pl/kmc
 
diff --git a/debian/changelog b/debian/changelog
index a63afc6..f4d7caf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,13 @@
-kmc (3.1.1+dfsg-4) UNRELEASED; urgency=medium
+kmc (3.1.2rc1+git20201001.1.a664708-1) UNRELEASED; urgency=medium
 
+  [ Michael R. Crusoe ]
   * Team upload.
   * debian/control: mark libkmc-dev as Multi-Arch: same
 
- -- Michael R. Crusoe <crusoe@debian.org>  Mon, 25 Jan 2021 08:04:44 +0100
+  [ Debian Janitor ]
+  * New upstream snapshot.
+
+ -- Michael R. Crusoe <crusoe@debian.org>  Mon, 26 Apr 2021 22:01:23 -0000
 
 kmc (3.1.1+dfsg-3) unstable; urgency=medium
 
diff --git a/kmc_api/mmer.h b/kmc_api/mmer.h
index 0d64f40..d4e7e77 100644
--- a/kmc_api/mmer.h
+++ b/kmc_api/mmer.h
@@ -37,7 +37,7 @@ class CMmer
 			return false;
 		if ((mmer & 0x3f) == 0x3b)            // TGT suffix
 			return false;
-		if ((mmer & 0x3c) == 0x3c)            // TG* suffix
+		if ((mmer & 0x3c) == 0x3c)            // TG* suffix !!!! consider issue #152
 			return false;
 
 		for (uint32 j = 0; j < len - 3; ++j)
diff --git a/kmc_tools/kmc1_db_reader.h b/kmc_tools/kmc1_db_reader.h
index 1954c6f..1a713ea 100644
--- a/kmc_tools/kmc1_db_reader.h
+++ b/kmc_tools/kmc1_db_reader.h
@@ -457,13 +457,14 @@ template<unsigned SIZE> void CKMC1DbReader<SIZE>::open_files()
 	suffix_file_name = desc.file_src + ".kmc_suf";
 
 	suffix_file = fopen(suffix_file_name.c_str(), "rb");
-	setvbuf(suffix_file, NULL, _IONBF, 0);
-
+	
 	if (!suffix_file)
 	{
 		std::cerr << "Error: cannot open file: " << suffix_file_name << "\n";
 		exit(1);
+	
 	}
+	
 	setvbuf(suffix_file, NULL, _IONBF, 0);
 
 	char marker[4];
@@ -498,13 +499,14 @@ template<unsigned SIZE> void CKMC1DbReader<SIZE>::open_files()
 	prefix_file_name = desc.file_src + ".kmc_pre";
 
 	prefix_file = fopen(prefix_file_name.c_str(), "rb");
-	setvbuf(prefix_file, NULL, _IONBF, 0);
-
+	
 	if (!prefix_file)
 	{
 		std::cerr << "Error: cannot open file: " << prefix_file_name << "\n";
 		exit(1);
 	}
+	setvbuf(prefix_file, NULL, _IONBF, 0);
+
 	my_fseek(prefix_file, 4 + sizeof(uint64), SEEK_SET);//skip KMCP and first value as it must be 0
 
 }
diff --git a/kmc_tools/kmc1_db_writer.h b/kmc_tools/kmc1_db_writer.h
index 18d3099..819b44d 100644
--- a/kmc_tools/kmc1_db_writer.h
+++ b/kmc_tools/kmc1_db_writer.h
@@ -123,15 +123,16 @@ bundles_queue(DEFAULT_CIRCULAL_QUEUE_CAPACITY)
 	std::string kmc_suf_file_name = output_desc.file_src + ".kmc_suf";
 
 	kmc_pre = fopen(kmc_pre_file_name.c_str(), "wb");
-	setvbuf(kmc_pre, NULL, _IONBF, 0);
-
+	
 	if (!kmc_pre)
 	{
 		std::cerr << "Error: cannot open file : " << kmc_pre_file_name << "\n";
 		exit(1);
 	}
+
+	setvbuf(kmc_pre, NULL, _IONBF, 0);
+
 	kmc_suf = fopen(kmc_suf_file_name.c_str(), "wb");
-	setvbuf(kmc_suf, NULL, _IONBF, 0);
 
 	if (!kmc_suf)
 	{
@@ -139,6 +140,7 @@ bundles_queue(DEFAULT_CIRCULAL_QUEUE_CAPACITY)
 		std::cerr << "Error: cannot open file : " << kmc_suf_file_name << "\n";
 		exit(1);
 	}
+	setvbuf(kmc_suf, NULL, _IONBF, 0);
 
 	setvbuf(kmc_pre, NULL, _IONBF, 0);
 	setvbuf(kmc_suf, NULL, _IONBF, 0);
diff --git a/kmer_counter/fastq_reader.cpp b/kmer_counter/fastq_reader.cpp
index 853d336..a0e7a8a 100644
--- a/kmer_counter/fastq_reader.cpp
+++ b/kmer_counter/fastq_reader.cpp
@@ -42,7 +42,7 @@ CFastqReader::CFastqReader(CMemoryMonitor *_mm, CMemoryPoolWithBamSupport *_pmm_
 	kmer_len = _kmer_len;
 
 	// Size and pointer for the buffer
-	part_size = 1 << 23;
+	part_size = 1 << 23;	
 	part = nullptr;
 
 	containsNextChromosome = false;
@@ -61,7 +61,7 @@ CFastqReader::~CFastqReader()
 //----------------------------------------------------------------------------------
 // Set part size of the buffer
 bool CFastqReader::SetPartSize(uint64 _part_size)
-{
+{	
 	if (_part_size < (1 << 20) || _part_size >(1 << 30))
 		return false;
 
@@ -406,7 +406,7 @@ bool CFastqReader::GetPartFromMultilneFasta(uchar *&_part, uint64 &_size)
 			int64 tmp = i;
 			bool next_line = SkipNextEOL(part, i, total_filled);
 			if (!next_line)
-				i = total_filled;
+				i = total_filled; 
 			copy(part + tmp, part + i, part + pos);
 			last_header_pos = pos;
 			pos += i - tmp;
@@ -468,6 +468,33 @@ FORCE_INLINE bool CFastqReader::GetNextSymbOfLongReadRecord(uchar& res, int64& p
 	return true;
 }
 
+void CFastqReader::CleanUpAfterLongFastaRead()
+{
+	pmm_fastq->reserve(part);
+
+	uchar symb;
+	int64 in_part = 0;
+	int64 skip_pos = 0;	
+	while (GetNextSymbOfLongReadRecord(symb, skip_pos, in_part))
+	{
+		if (symb == '\n' || symb == '\r')
+			;
+		else
+		{				
+			if (symb != '>')
+			{
+				cerr << "Error: Wrong input file!\n";				
+				exit(1);
+			}
+			std::copy(part + skip_pos - 1, part + in_part, part);
+			part_filled = in_part - (skip_pos - 1);
+			return;				
+		}				
+	}
+
+	//the file has ended
+	part_filled = 0;
+}
 void CFastqReader::CleanUpAfterLongFastqRead(uint32 number_of_lines_to_skip)
 {
 	pmm_fastq->reserve(part);
@@ -540,6 +567,7 @@ bool CFastqReader::GetPartNew(uchar *&_part, uint64 &_size, ReadType& read_type)
 
 	if (data_src.Finished() && !long_read_in_progress)
 	{
+		read_type = ReadType::normal_read;
 		_part = part;
 		_size = total_filled;
 
@@ -554,6 +582,49 @@ bool CFastqReader::GetPartNew(uchar *&_part, uint64 &_size, ReadType& read_type)
 	}									// Look for the end of the last complete record in a buffer
 	else if (file_type == fasta)			// FASTA files
 	{
+		if (long_read_in_progress)
+		{			
+			//check if there is EOL in the data
+			int64 pos = 0;
+			for (; pos < total_filled; ++pos)
+			{
+				if (part[pos] == '\n' || part[pos] == '\r')
+				{
+					long_read_in_progress = false;
+					break;
+				}
+			}
+
+			if (!long_read_in_progress)
+			{
+				_part = part;
+				_size = pos;
+
+				//all from this part was readed, maybe there is another EOL character in the file
+				if(pos == total_filled)
+					CleanUpAfterLongFastaRead();
+				else //there is still some important data in the part!!
+				{
+					//skip possible eol
+					for (; pos < total_filled; ++pos)
+						if (part[pos] != '\n' && part[pos] != '\r')
+							break;
+
+					pmm_fastq->reserve(part);
+					std::copy(_part + pos, _part + total_filled, part);
+					part_filled = total_filled - pos;
+				}
+			}
+			else
+			{
+				_part = part;
+				_size = total_filled;
+				pmm_fastq->reserve(part);
+				std::copy(_part + total_filled - kmer_len + 1, _part + total_filled, part);
+				part_filled = kmer_len - 1;
+			}
+			return true;
+		}
 		// Looking for a FASTA record at the end of the area
 		i = total_filled - 1;
 		int64 start, end;
@@ -583,8 +654,45 @@ bool CFastqReader::GetPartNew(uchar *&_part, uint64 &_size, ReadType& read_type)
 		// Looking for a FASTQ record at the end of the area
 		if (!success)
 		{
-			cerr << "Error: Wrong input file!\n";
-			exit(1);
+			if (readed_lines == 2) //because if successfully readed full 2 lines in the worst case there is only one read that begins at the buffer start, and there is only onle fasta record
+			{
+				std::cerr << "Error: some error while reading fasta file, please contact authors\n";
+				exit(1);
+			}
+			k = 4 - readed_lines;
+			if (line_start[k] != 0)
+			{
+				std::cerr << "Error: some error while reading fasta file, please contact authors\n";
+				exit(1);
+			}
+			if (part[0] != '>')
+			{
+				cerr << "Error: Wrong input file!\n";				
+				exit(1);
+			}
+
+			if (readed_lines == 1)
+			{
+				long_read_in_progress = true;				
+
+				_part = part;
+				_size = total_filled;
+				read_type = ReadType::long_read;
+
+				//copy last k-1 symbols
+				pmm_fastq->reserve(part);
+				copy(_part + total_filled - kmer_len + 1, _part + total_filled, part);
+				part_filled = kmer_len - 1;
+
+				return true;
+			}
+			else 
+			{
+				std::cerr << "Error: some error while reading fasta file, please contact authors\n";
+				exit(1);
+			}
+
+			return true;
 		}
 
 		_part = part;
@@ -756,14 +864,14 @@ bool CFastqReader::GetPartNew(uchar *&_part, uint64 &_size, ReadType& read_type)
 
 //----------------------------------------------------------------------------------
 // Skip to next EOL from the current position in a buffer
-bool CFastqReader::SkipNextEOL(uchar *part, int64 &pos, int64 max_pos)
+bool CFastqReader::SkipNextEOL(uchar *part, int64 &pos, int64 size)
 {
 	int64 i;
-	for (i = pos; i < max_pos - 2; ++i)
+	for (i = pos; i < size - 1; ++i)
 		if ((part[i] == '\n' || part[i] == '\r') && !(part[i + 1] == '\n' || part[i + 1] == '\r'))
 			break;
 
-	if (i >= max_pos - 2)
+	if (i >= size - 1)
 		return false;
 
 	pos = i + 1;
@@ -1072,7 +1180,7 @@ CWFastqReader::CWFastqReader(CKMCParams &Params, CKMCQueues &Queues, CBinaryPack
 	binary_pack_queue = _binary_pack_queue;
 	missingEOL_at_EOF_counter = Queues.missingEOL_at_EOF_counter;
 	bam_task_manager = Queues.bam_task_manager;
-	part_size = Params.fastq_buffer_size;
+	part_size = Params.fastq_buffer_size; 
 	part_queue = Queues.part_queue;
 	file_type = Params.file_type;
 	kmer_len = Params.p_k;
diff --git a/kmer_counter/fastq_reader.h b/kmer_counter/fastq_reader.h
index 9afab1b..4fbfe02 100644
--- a/kmer_counter/fastq_reader.h
+++ b/kmer_counter/fastq_reader.h
@@ -104,7 +104,7 @@ class CFastqReader {
 	
 	bool containsNextChromosome; //for multiline_fasta processing
 
-	bool SkipNextEOL(uchar *part, int64 &pos, int64 max_pos);
+	bool SkipNextEOL(uchar *part, int64 &pos, int64 size);
 
 	void GetFullLineFromEnd(int64& line_sart, int64& line_end, uchar* buff, int64& pos);
 	
@@ -115,6 +115,7 @@ class CFastqReader {
 
 	void CleanUpAfterLongFastqRead(uint32 number_of_lines_to_skip);
 
+	void CleanUpAfterLongFastaRead();
 	void FixEOLIfNeeded(uchar* part, int64& size);	
 public:
 	CFastqReader(CMemoryMonitor *_mm, CMemoryPoolWithBamSupport *_pmm_fastq, input_type _file_type, int _kmer_len, 
diff --git a/kmer_counter/kmc.h b/kmer_counter/kmc.h
index 068015a..9eacf2b 100644
--- a/kmer_counter/kmc.h
+++ b/kmer_counter/kmc.h
@@ -156,6 +156,7 @@ template <unsigned SIZE> void CKMC<SIZE>::SetParams(CKMCParams &_Params)
 	Params.both_strands   = Params.p_both_strands;
 	Params.without_output = Params.p_without_output;
 	Params.use_strict_mem = Params.p_strict_mem;
+	Params.homopolymer_compressed = Params.p_homopolymer_compressed;
 	Params.mem_mode		  = Params.p_mem_mode;
 
 	
diff --git a/kmer_counter/kmer_counter.cpp b/kmer_counter/kmer_counter.cpp
index e8f7891..405e7cd 100644
--- a/kmer_counter/kmer_counter.cpp
+++ b/kmer_counter/kmer_counter.cpp
@@ -152,6 +152,7 @@ void usage()
 		 << "  -k<len> - k-mer length (k from " << MIN_K << " to " << MAX_K << "; default: 25)\n"
 		 << "  -m<size> - max amount of RAM in GB (from 1 to 1024); default: 12\n"
 		 << "  -sm - use strict memory mode (memory limit from -m<n> switch will not be exceeded)\n"
+		 << "  -hc - count homopolymer compressed k-mers (approximate and experimental)\n"
 		 << "  -p<par> - signature length (5, 6, 7, 8, 9, 10, 11); default: 9\n"
 		 << "  -f<a/q/m/bam> - input in FASTA format (-fa), FASTQ format (-fq), multi FASTA (-fm) or BAM (-fbam); default: FASTQ\n"	
 		 << "  -ci<value> - exclude k-mers occurring less than <value> times (default: 2)\n"
@@ -238,7 +239,7 @@ bool parse_parameters(int argc, char *argv[])
 			Params.p_cx = atoll(&argv[i][3]);
 		// Maximal counter value
 		else if (strncmp(argv[i], "-cs", 3) == 0)
-			Params.p_cs = atoll(&argv[i][3]);		
+			Params.p_cs = atoll(&argv[i][3]);
 		// Set p1
 		else if (strncmp(argv[i], "-p", 2) == 0)
 		{
@@ -269,6 +270,8 @@ bool parse_parameters(int argc, char *argv[])
 			Params.p_verbose = true;
 		else if (strncmp(argv[i], "-sm", 3) == 0 && strlen(argv[i]) == 3)
 			Params.p_strict_mem = true;
+		else if (strncmp(argv[i], "-hc", 3) == 0 && strlen(argv[i]) == 3)
+			Params.p_homopolymer_compressed = true;
 		else if (strncmp(argv[i], "-r", 2) == 0)
 			Params.p_mem_mode = true;
 		else if(strncmp(argv[i], "-b", 2) == 0)
@@ -494,7 +497,7 @@ int _tmain(int argc, _TCHAR* argv[])
 	delete app;
 
 	cout << "1st stage: " << time1 << "s\n"
-	     << "2nd stage: " << time2  << "s\n";
+	     << "2nd stage: " << time2 << "s\n";
 
 	bool display_strict_mem_stats = Params.p_strict_mem && !was_small_k_opt;
 	if (display_strict_mem_stats)
diff --git a/kmer_counter/mmer.h b/kmer_counter/mmer.h
index fa00568..7dc70ca 100644
--- a/kmer_counter/mmer.h
+++ b/kmer_counter/mmer.h
@@ -37,7 +37,7 @@ class CMmer
 			return false;
 		if ((mmer & 0x3f) == 0x3b)            // TGT suffix
 			return false;
-		if ((mmer & 0x3c) == 0x3c)            // TG* suffix
+		if ((mmer & 0x3c) == 0x3c)            // TG* suffix !!!! consider issue #152
 			return false;
 
 		for (uint32 j = 0; j < len - 3; ++j)
diff --git a/kmer_counter/params.h b/kmer_counter/params.h
index a9d9495..3d63821 100644
--- a/kmer_counter/params.h
+++ b/kmer_counter/params.h
@@ -35,6 +35,7 @@ struct CKMCParams {
 	int64 p_cx;							// do not count k-mers occurring more than
 	int64 p_cs;							// maximal counter value	
 	bool p_strict_mem;					// use strict memory limit mode
+	bool p_homopolymer_compressed;		// count homopolymer compressed k-mers
 	bool p_mem_mode;					// use RAM instead of disk	
 	input_type p_file_type;				// input in FASTA format
 	bool p_verbose;						// verbose mode
@@ -98,6 +99,7 @@ struct CKMCParams {
 	int64 cutoff_max;			// exclude k-mers occurring more than times
 	int64 counter_max;		// maximal counter value	
 	bool use_strict_mem;	// use strict memory limit mode
+	bool homopolymer_compressed; //count homopolymer compressed k-mers
 	bool both_strands;		// find canonical representation of each k-mer
 	bool mem_mode;			// use RAM instead of disk
 
@@ -150,6 +152,7 @@ struct CKMCParams {
 		p_cx = 1000000000;
 		p_cs = 255;		
 		p_strict_mem = false;
+		p_homopolymer_compressed = false;
 		p_mem_mode = false;		
 		p_file_type = fastq;
 		p_verbose = false;
diff --git a/kmer_counter/splitter.cpp b/kmer_counter/splitter.cpp
index 48391a6..301969d 100644
--- a/kmer_counter/splitter.cpp
+++ b/kmer_counter/splitter.cpp
@@ -11,7 +11,6 @@ Date   : 2019-05-19
 #include "stdafx.h"
 #include "splitter.h"
 
-
 //************************************************************************************************************
 // CSplitter class - splits kmers into bins according to their signatures
 //************************************************************************************************************
@@ -35,7 +34,7 @@ CSplitter::CSplitter(CKMCParams &Params, CKMCQueues &Queues)
 
 	mem_part_pmm_bins = Params.mem_part_pmm_bins;
 
-	mem_part_pmm_reads = Params.mem_part_pmm_reads;
+	mem_part_pmm_reads = Params.mem_part_pmm_reads; 
 
 	s_mapper = Queues.s_mapper;
 
@@ -51,6 +50,8 @@ CSplitter::CSplitter(CKMCParams &Params, CKMCQueues &Queues)
 
 	n_reads = 0;
 	bins = nullptr;
+
+	homopolymer_compressed = Params.homopolymer_compressed;
 }
 
 void CSplitter::InitBins(CKMCParams &Params, CKMCQueues &Queues)
@@ -66,20 +67,45 @@ void CSplitter::InitBins(CKMCParams &Params, CKMCQueues &Queues)
 	}
 }
 
+//----------------------------------------------------------------------------------
+// Parse long read, header_merker is '@' or '>'
+bool CSplitter::GetSeqLongRead(char *seq, uint32 &seq_size, uchar header_marker)
+{	
+	uint32 pos = 0;
+	//long read may or may not contain header
+	if (part_pos == 0 && part[0] == header_marker)
+	{
+		++n_reads;
+		for (; part[part_pos] != '\n' && part[part_pos] != '\r'; ++part_pos)
+			;
+	}
+	while (pos < mem_part_pmm_reads && part_pos < part_size)
+		seq[pos++] = codes[part[part_pos++]];
+	seq_size = pos;
+	if (part_pos < part_size)
+		part_pos -= kmer_len - 1;
+	return true;
+}
+
+
+
 //----------------------------------------------------------------------------------
 // Return a single record from FASTA/FASTQ data
 bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 {
+	if (part_pos >= part_size)
+		return false;
+
 	uchar c = 0;
 	uint32 pos = 0;
 
 	if (file_type == fasta)
-	{
-		// Title
-		if (part_pos >= part_size)
-			return false;
+	{		
+		if (read_type == ReadType::long_read)
+			return GetSeqLongRead(seq, seq_size, '>');
 		if (curr_read_len == 0)
 		{
+			// Title
 			c = part[part_pos++];
 			if (c != '>')
 				return false;
@@ -109,10 +135,11 @@ bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 				seq[pos++] = codes[c];
 			}
 
+			seq_size = pos;
+
 			if (part_pos >= part_size)
 				return true;
 
-			seq_size = pos;
 			curr_read_len = pos;
 
 			if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
@@ -132,10 +159,11 @@ bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 				seq[pos++] = codes[c];
 			}
 
+			seq_size = pos;
+
 			if (part_pos >= part_size)
 				return true;
 
-			seq_size = pos;
 			curr_read_len += pos - kmer_len + 1;
 
 			if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
@@ -144,6 +172,13 @@ bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 				return true;
 			}
 		}
+		
+		curr_read_len = 0;
+
+		//end of last record 
+		if (part_pos >= part_size)
+			return true;
+
 		if (part[part_pos++] >= 32)
 			part_pos--;
 		else if (part_pos >= part_size)
@@ -151,145 +186,123 @@ bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 	}
 	else if (file_type == fastq)
 	{
-		if (read_type == ReadType::long_read)
-		{
-			//long read may or may not contain header
-			if (part_pos >= part_size)
-				return false;
-
-			if (part_pos == 0 && part[0] == '@')
-			{
-				++n_reads;
-				for (; part[part_pos] != '\n' && part[part_pos] != '\r'; ++part_pos)
-					;
-			}
-			while(pos < mem_part_pmm_reads && part_pos < part_size)
-				seq[pos++] = codes[part[part_pos++]];
-			seq_size = pos;
-			if(part_pos < part_size)
-				part_pos -= kmer_len - 1;
-			return true;
-		}
-		else
+		if (read_type == ReadType::long_read)		
+			return GetSeqLongRead(seq, seq_size, '@');	
+	
+		if (curr_read_len == 0)
 		{
-
 			// Title
-			if (part_pos >= part_size)
+			c = part[part_pos++];
+			if (c != '@')
 				return false;
+			++n_reads;
 
-			if (curr_read_len == 0)
+			for (; part_pos < part_size;)
 			{
 				c = part[part_pos++];
-				if (c != '@')
-					return false;
-				++n_reads;
-
-				for (; part_pos < part_size;)
-				{
-					c = part[part_pos++];
-					if (c < 32)					// newliners
-						break;
-				}
-				if (part_pos >= part_size)
-					return false;
-
-				c = part[part_pos++];
-				if (c >= 32 || c == part[part_pos - 2]) //read may be empty
-					part_pos--;
-				else if (part_pos >= part_size)
-					return false;
-
-				// Sequence
-				for (; part_pos < part_size && pos < mem_part_pmm_reads;)
-				{
-					c = part[part_pos++];
-					if (c < 32)					// newliners
-						break;
-					seq[pos++] = codes[c];
-				}
-				if (part_pos >= part_size)
-					return false;
-
-				seq_size = pos;
-				curr_read_len = pos;
-
-				if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
-				{
-					part_pos -= kmer_len - 1;
-					return true;
-				}
-			}
-			else // we are inside read
-			{
-				// Sequence
-				for (; part_pos < part_size && pos < mem_part_pmm_reads;)
-				{
-					c = part[part_pos++];
-					if (c < 32)					// newliners
-						break;
-					seq[pos++] = codes[c];
-				}
-				if (part_pos >= part_size)
-					return false;
-
-				seq_size = pos;
-				curr_read_len += pos - kmer_len + 1;
-				if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
-				{
-					part_pos -= kmer_len - 1;
-					return true;
-				}
+				if (c < 32)					// newliners
+					break;
 			}
+			if (part_pos >= part_size)
+				return false;
 
 			c = part[part_pos++];
-			if (c >= 32)
+			if (c >= 32 || c == part[part_pos - 2]) //read may be empty
 				part_pos--;
 			else if (part_pos >= part_size)
 				return false;
 
-			// Plus
-			c = part[part_pos++];
+			// Sequence
+			for (; part_pos < part_size && pos < mem_part_pmm_reads;)
+			{
+				c = part[part_pos++];
+				if (c < 32)					// newliners
+					break;
+				seq[pos++] = codes[c];
+			}
 			if (part_pos >= part_size)
 				return false;
-			if (c != '+')
-				return false;
-			for (; part_pos < part_size;)
+
+			seq_size = pos;
+			curr_read_len = pos;
+
+			if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
+			{
+				part_pos -= kmer_len - 1;
+				return true;
+			}
+		}
+		else // we are inside read
+		{
+			// Sequence
+			for (; part_pos < part_size && pos < mem_part_pmm_reads;)
 			{
 				c = part[part_pos++];
 				if (c < 32)					// newliners
 					break;
+				seq[pos++] = codes[c];
 			}
 			if (part_pos >= part_size)
 				return false;
 
+			seq_size = pos;
+			curr_read_len += pos - kmer_len + 1;
+			if (pos >= mem_part_pmm_reads) // read is too long to fit into out buff, it will be splitted into multiple buffers
+			{
+				part_pos -= kmer_len - 1;
+				return true;
+			}
+		}
+
+		c = part[part_pos++];
+		if (c >= 32)
+			part_pos--;
+		else if (part_pos >= part_size)
+			return false;
+
+		// Plus
+		c = part[part_pos++];
+		if (part_pos >= part_size)
+			return false;
+		if (c != '+')
+			return false;
+		for (; part_pos < part_size;)
+		{
 			c = part[part_pos++];
-			if (c >= 32 || c == part[part_pos - 2]) //qual may be empty
-				part_pos--;
-			else if (part_pos >= part_size)
-				return false;
+			if (c < 32)					// newliners
+				break;
+		}
+		if (part_pos >= part_size)
+			return false;
 
-			part_pos += curr_read_len;
-			curr_read_len = 0;
+		c = part[part_pos++];
+		if (c >= 32 || c == part[part_pos - 2]) //qual may be empty
+			part_pos--;
+		else if (part_pos >= part_size)
+			return false;
 
-			// Quality
+		// Quality
+		part_pos += curr_read_len; //skip quality
+		
+		curr_read_len = 0;
 
-			if (part_pos >= part_size)
-				return false;
-			c = part[part_pos++];
+		if (part_pos >= part_size)
+			return false;
+		c = part[part_pos++];
 
-			if (part_pos >= part_size)
-				return true;
+		//end of last record 
+		if (part_pos >= part_size)
+			return true;
 
-			if (part[part_pos++] >= 32)
-				part_pos--;
-			else if (part_pos >= part_size)
-				return true;
-		}
+		//may be additional EOL character 
+		if (part[part_pos++] >= 32)
+			part_pos--;
+		else if (part_pos >= part_size)
+			return true;
+		
 	}
 	else if (file_type == multiline_fasta)
 	{
-		if (part_pos >= part_size)
-			return false;
 		if (part[part_pos] == '>')//need to ommit header
 		{
 			++n_reads;
@@ -407,6 +420,20 @@ bool CSplitter::GetSeq(char *seq, uint32 &seq_size, ReadType read_type)
 	return (c == '\n' || c == '\r');
 }
 
+//----------------------------------------------------------------------------------
+void CSplitter::HomopolymerCompressSeq(char* seq, uint32 &seq_size)
+{
+	if (seq_size <= 1)
+		return;
+
+	uint32 read_pos = 1;
+	uint32 write_pos = 0;
+	for (; read_pos < seq_size; ++read_pos)
+		if (seq[read_pos] != seq[write_pos])
+			seq[++write_pos] = seq[read_pos];
+	seq_size = write_pos + 1;
+}
+
 //----------------------------------------------------------------------------------
 // Calculate statistics of m-mers
 void CSplitter::CalcStats(uchar* _part, uint64 _part_size, ReadType read_type, uint32* _stats)
@@ -427,6 +454,8 @@ void CSplitter::CalcStats(uchar* _part, uint64 _part_size, ReadType read_type, u
 
 	while (GetSeq(seq, seq_size, read_type))
 	{
+		if (homopolymer_compressed)
+			HomopolymerCompressSeq(seq, seq_size);
 		i = 0;
 		len = 0;
 		while (i + kmer_len - 1 < seq_size)
@@ -527,7 +556,9 @@ bool CSplitter::ProcessReads(uchar *_part, uint64 _part_size, ReadType read_type
 	uint32 len;//length of extended kmer
 
 	while (GetSeq(seq, seq_size, read_type))
-	{
+	{		
+		if (homopolymer_compressed)
+			HomopolymerCompressSeq(seq, seq_size);
 		//if (file_type != multiline_fasta && file_type != fastq) //read conting moved to GetSeq
 		//	n_reads++;
 		i = 0;
@@ -653,8 +684,10 @@ bool CSplitter::ProcessReadsSmallK(uchar *_part, uint64 _part_size, ReadType rea
 	if (both_strands)
 		while (GetSeq(seq, seq_size, read_type))
 		{
-			if (file_type != multiline_fasta)
-				n_reads++;
+			if (homopolymer_compressed)
+				HomopolymerCompressSeq(seq, seq_size);
+			//if (file_type != multiline_fasta)
+			//	n_reads++;
 
 			// Init k-mer
 			kmer_str.clear();
@@ -706,8 +739,10 @@ bool CSplitter::ProcessReadsSmallK(uchar *_part, uint64 _part_size, ReadType rea
 	else
 		while (GetSeq(seq, seq_size, read_type))
 		{
-			if (file_type != multiline_fasta)
-				n_reads++;
+			if (homopolymer_compressed)
+				HomopolymerCompressSeq(seq, seq_size);
+			//if (file_type != multiline_fasta)
+			//	n_reads++;
 
 			// Init k-mer
 			kmer_str.clear();
@@ -805,7 +840,7 @@ void CWSplitter::operator()()
 		uint64 size;
 		ReadType read_type;
 		if (pq->pop(part, size, read_type))
-		{
+		{			
 			spl->ProcessReads(part, size, read_type);
 			pmm_fastq->free(part);
 		}
diff --git a/kmer_counter/splitter.h b/kmer_counter/splitter.h
index c6bd082..a4f096c 100644
--- a/kmer_counter/splitter.h
+++ b/kmer_counter/splitter.h
@@ -54,8 +54,14 @@ class CSplitter {
 
 	CSignatureMapper* s_mapper;
 
+	bool homopolymer_compressed;
+
+	bool GetSeqLongRead(char *seq, uint32 &seq_size, uchar header_marker);
+
 	bool GetSeq(char *seq, uint32 &seq_size, ReadType read_type);
 
+	void HomopolymerCompressSeq(char* seq, uint32 &seq_size);
+
 public:
 	static uint32 MAX_LINE_SIZE;