function [stat_table, contrast_table] = my_GLS(X, y, C, W, xnames, cnames)
[C, var_chat, se_chat, t_chat, pval_chat] = deal([]);
contrast_table = table();
xnames = cell(1, size(X, 2))';
cnames = cell(1, size(C, 2))';
% assume they are a vector
if size(W, 1) ~= size(X, 1), error('W is the wrong size. Should be [n x 1] or [n x n]'), end
% -------------------------------------------
% remove nans from X and y
% Note: You need CANlabCore tools on your path for this!
% You can omit this line if you don't have NaNs (missing data)
[wasnan, X, y] = nanremove(X, y);
bhat = xtxi * X' * W * y;
sigma_sq = e'* W * e ./ (n - p); % residual variance
var_bhat = sigma_sq * xtxi;
t = bhat ./ (diag(var_bhat) .^ .5);
pval = 2 * (1 - tcdf(abs(t), dfe));
se = sqrt(diag(var_bhat)); % standard error
var_chat = sigma_sq * C' * xtxi * C;
se_chat = diag(var_chat) .^ 0.5;
t_chat = chat ./ se_chat;
pval_chat = 2 * (1 - tcdf(abs(t_chat), dfe));
% Collect and print output tables
% -------------------------------------------
stat_table = table(xnames, bhat, se, t, pval, 'VariableNames', {'Name', 'bhat', 'SE', 't', 'P'});
disp('Model parameters:')
contrast_table = table(cnames, chat, se_chat, t_chat, pval_chat, 'VariableNames', {'Contrast', 'bhat', 'SE', 't', 'P'});