function Vout = common_collector(Vin, approx)

  if (approx == 1)
    omega = @omega1;
  elseif (approx == 2)
    omega = @omega2;
  elseif (approx == 3)
    omega = @omega3;
  elseif (approx == 4)
    omega = @omega4;
  elseif (approx == 5)
    omega = @omegaExact;
  endif
  
  % component values
  
  VT = 0.026;
	Is = 1e-16;
	Bf = 100.0;
	Re = 1e3;
	Vplus = 9.0;
  
  % absolute constants
  
  InvVT = 1.0 / VT;
	k1 = Is * Re;
  k2 = 1.0 / Bf;
  k = log(InvVT * k1 * (1.0 + k2));
  
  % audio-rate
  
	Vx = k1 * (expApprox(InvVT * (Vin - Vplus)) + k2);
	Vout = VT * omega(InvVT * (Vin + Vx) + k) - Vx;
  
endfunction

function y = omega1(x)
  y = max(0, x);
endfunction

function y = omega2(x)
  x1 = -3.684303659906469;
	x2 = 1.972967391708859;
	a = 9.451797158780131e-3;
	b = 1.126446405111627e-1;
	c = 4.451353886588814e-1;
	d = 5.836596684310648e-1;
  y = x;
  y(x<x2) = d + x(x<x2) .* (c + x(x<x2) .* (b + x(x<x2) .* a));
  y(x<x1) = 0;
endfunction

function y = omega3(x)
  x1 = -3.341459552768620;
	x2 = 8;
	a = -1.314293149877800e-3;
	b = 4.775931364975583e-2;
	c = 3.631952663804445e-1;
	d = 6.313183464296682e-1;
  y = x - logApprox(x);
  y(x<x2) = d + x(x<x2) .* (c + x(x<x2) .* (b + x(x<x2) .* a));
  y(x<x1) = 0;
endfunction

function y = omega4(x)
  y = omega3(x);
  y = y - (y - expApprox(x - y)) ./ (y + 1);
endfunction

function y = omegaExact(x)
  y = lambertw(exp(x));
endfunction

# the following functions simulate the log/exp approximations described in the paper

function y = log2Approx(x)
  e = floor(log2(x));
  d = x ./ (2 .^ e);
  y = e - 2.213475204444817 + d .* (3.148297929334117 + d .* (-1.098865286222744 + d .* 0.1640425613334452));
endfunction

function y = logApprox(x)
  y = 0.693147180559945 * log2Approx(x);
endfunction

function y = pow2Approx(x)
  l = floor(x);
  f = x - l;
  y = (2 .^ l) .* (1.0 + f .* (0.6931471805599453 + f .* (0.2274112777602189 + f .* 0.07944154167983575)));
endfunction

function y = expApprox(x)
  y = pow2Approx(1.442695040888963 * x);
endfunction