diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9fec7abfcf24439f97b3e8a2747fb3e2f7a404a8..df8a4d769477f175ceaedf9369418b24851f07ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SRC_FILES
 	translators.cpp
 	randomgen.cpp
 	compcache.cpp
+	linearregession.cpp
 )
 
 set(API_HEADERS_CPP_DIR eisgenerator/)
diff --git a/basicmath.cpp b/basicmath.cpp
index 84db4b396f9b9343d8d73ee5bc13dfdf2c3b0d0e..dda06ece53ba619863f11998215a12907a5b17e7 100644
--- a/basicmath.cpp
+++ b/basicmath.cpp
@@ -2,9 +2,11 @@
 #include <algorithm>
 #include <random>
 #include <limits>
+#include <stdexcept>
 
 #include "eistype.h"
 #include "log.h"
+#include "linearregession.h"
 
 static size_t gradIndex(size_t dataSize, size_t inputIndex)
 {
@@ -259,6 +261,25 @@ getLrClosest(const eis::DataPoint& dp, std::vector<eis::DataPoint>::const_iterat
 	return {left, right};
 }
 
+static bool omegaCompeare(std::pair<fvalue, std::vector<eis::DataPoint>::const_iterator> a,
+                          std::pair<fvalue, std::vector<eis::DataPoint>::const_iterator> b)
+{
+	return a.first < b.first;
+}
+
+static std::vector<std::pair<fvalue, std::vector<eis::DataPoint>::const_iterator>>
+getSortedOmegaDistances(fvalue omega,
+                        std::vector<eis::DataPoint>::const_iterator start,
+                        std::vector<eis::DataPoint>::const_iterator end)
+{
+	std::vector<std::pair<fvalue, std::vector<eis::DataPoint>::const_iterator>> out;
+
+	for(std::vector<eis::DataPoint>::const_iterator it = start; it != end; it++)
+		out.push_back({std::abs(it->omega-omega), it});
+	std::sort(out.begin(), out.end(), omegaCompeare);
+	return out;
+}
+
 static eis::DataPoint linearInterpolatePoint(fvalue omega, const eis::DataPoint& left, const eis::DataPoint& right)
 {
 	assert(left.omega <= omega);
@@ -269,7 +290,42 @@ static eis::DataPoint linearInterpolatePoint(fvalue omega, const eis::DataPoint&
 	return eis::DataPoint(left.im+sloap*(omega - left.omega), omega);
 }
 
-std::vector<eis::DataPoint> eis::fitToFrequencies(std::vector<fvalue> omegas, const std::vector<eis::DataPoint>& data)
+static eis::DataPoint linearExtrapoloatePoint(fvalue omega, const std::vector<eis::DataPoint>& data)
+{
+	if(data.size() < 3)
+		throw std::invalid_argument("extrapolation requires at least 3 points");
+
+	std::vector<std::pair<fvalue, std::vector<eis::DataPoint>::const_iterator>> dist;
+	dist = getSortedOmegaDistances(omega, data.begin(), data.end());
+
+	std::vector<fvalue> omegas;
+	std::vector<fvalue> im;
+	std::vector<fvalue> re;
+	omegas.reserve(dist.size());
+	im.reserve(dist.size());
+	re.reserve(dist.size());
+	for(size_t i = 0; i < 3; ++i)
+	{
+		omegas.push_back(dist[i].second->omega);
+		im.push_back(dist[i].second->im.imag());
+		re.push_back(dist[i].second->im.real());
+	}
+
+	LinearRegessionCalculator realReg(omegas, re);
+	LinearRegessionCalculator imagReg(omegas, im);
+
+	eis::Log(eis::Log::DEBUG)<<"Real regression:\n\toffset: "<<realReg.offset
+		<<"\n\tsloap: "<<realReg.slope<<"\n\tstderror: "<<realReg.stdError;
+	eis::Log(eis::Log::DEBUG)<<"Imag regression:\n\toffset: "<<imagReg.offset
+		<<"\n\tsloap: "<<imagReg.slope<<"\n\tstderror: "<<imagReg.stdError;
+
+	if(realReg.stdError > 1 || imagReg.stdError > 1)
+		throw std::invalid_argument("input data must be sufficantly linear");
+
+	return eis::DataPoint({realReg.slope*omega+realReg.offset, imagReg.slope*omega+imagReg.offset}, omega);
+}
+
+std::vector<eis::DataPoint> eis::fitToFrequencies(std::vector<fvalue> omegas, const std::vector<eis::DataPoint>& data, bool linearExtrapolation)
 {
 	std::vector<eis::DataPoint> out;
 	out.reserve(omegas.size());
@@ -289,15 +345,45 @@ std::vector<eis::DataPoint> eis::fitToFrequencies(std::vector<fvalue> omegas, co
 			eis::Log(eis::Log::DEBUG)<<"\tRight "<<lr.second->omega<<','<<lr.second->im;
 
 		if(lr.first == lr.second)
+		{
 			dp.im = lr.first->im;
+		}
 		else if(lr.first != data.end() && lr.second != data.end())
+		{
 			dp = linearInterpolatePoint(dp.omega, *lr.first, *lr.second);
+		}
 		else if(lr.first != data.end() && lr.second == data.end())
-			dp.im = lr.first->im;
+		{
+			try
+			{
+				if(!linearExtrapolation)
+					dp.im = lr.first->im;
+				else
+					dp = linearExtrapoloatePoint(dp.omega, data);
+			}
+			catch (const std::invalid_argument& ex)
+			{
+				dp.im = lr.first->im;
+			}
+		}
 		else if(lr.first == data.end() && lr.second != data.end())
-			dp.im = lr.second->im;
+		{
+			try
+			{
+				if(!linearExtrapolation)
+					dp.im = lr.second->im;
+				else
+					dp = linearExtrapoloatePoint(dp.omega, data);
+			}
+			catch (const std::invalid_argument& ex)
+			{
+				dp.im = lr.second->im;
+			}
+		}
 		else
+		{
 			assert(false);
+		}
 	}
 
 	return out;
diff --git a/eisgenerator/basicmath.h b/eisgenerator/basicmath.h
index f1c73813c03ebb40b65043e9a673f9471c66daf6..1daab85c16628f8648497f53caa38730a36446b8 100644
--- a/eisgenerator/basicmath.h
+++ b/eisgenerator/basicmath.h
@@ -18,6 +18,8 @@ namespace eis
 	void noise(std::vector<eis::DataPoint>& data, double amplitude, bool relative);
 	void removeDuplicates(std::vector<eis::DataPoint>& data);
 	bool fvalueEq(fvalue a, fvalue b, unsigned int ulp = 4);
-	std::vector<eis::DataPoint> fitToFrequencies(std::vector<fvalue> omegas, const std::vector<eis::DataPoint>& data);
+	std::vector<eis::DataPoint> fitToFrequencies(std::vector<fvalue> omegas,
+	                                             const std::vector<eis::DataPoint>& data,
+	                                             bool linearExtrapolation = false);
 }
 
diff --git a/linearregession.cpp b/linearregession.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d555670d1e1c822ac281a1afbb63ac92cea2c69
--- /dev/null
+++ b/linearregession.cpp
@@ -0,0 +1,38 @@
+#include "linearregession.h"
+#include <stdexcept>
+#include <cmath>
+
+LinearRegessionCalculator::LinearRegessionCalculator(const std::vector < fvalue > &xValues, const std::vector < fvalue > &yValues)
+{
+	if(xValues.size() == yValues.size())
+	{
+		this->xValues = xValues;
+		this->yValues = yValues;
+
+		fvalue sumY = 0;
+		fvalue sumX = 0;
+		fvalue sumXTimesY = 0;
+		fvalue sumSquaredX = 0;
+		fvalue sumSquaredY = 0;
+		for(unsigned i = 0; i < xValues.size(); i++)
+		{
+			sumY += yValues[i];
+			sumX += xValues[i];
+			sumSquaredX += xValues[i] * xValues[i];
+			sumSquaredY += yValues[i] * yValues[i];
+			sumXTimesY += xValues[i] * yValues[i];
+		}
+
+		slope = (sumXTimesY - (sumX * sumY) / xValues.size()) / (sumSquaredX - (sumX * sumX) / xValues.size());
+		offset = sumY / xValues.size() - slope * (sumX / xValues.size());
+
+		fvalue error =
+		    (xValues.size() * sumSquaredY - sumY * sumY -
+		     slope * slope * (xValues.size() * sumSquaredX - sumX * sumX)) / (xValues.size() * (xValues.size() - 2));
+		stdError = sqrt((error * error * xValues.size()) / (xValues.size() * sumSquaredX - sumX * sumX));
+	}
+	else
+	{
+		throw std::invalid_argument("xValues and yValues need to be the same size");
+	}
+}
diff --git a/linearregession.h b/linearregession.h
new file mode 100644
index 0000000000000000000000000000000000000000..5061e02c5413b67742238ebf4db9d24bfd3b1abe
--- /dev/null
+++ b/linearregession.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <vector>
+#include "eisgenerator/eistype.h"
+
+class LinearRegessionCalculator
+{
+public:
+	std::vector < fvalue > xValues;
+	std::vector < fvalue > yValues;
+
+	fvalue slope;
+	fvalue offset;
+	fvalue stdError;
+
+	LinearRegessionCalculator(const std::vector < fvalue > &xValues, const std::vector < fvalue > &yValues);
+};