Phaseshaping Osc Algorithms

EDIT: The code now looks perfect on the plot for every vertical value.
But the transitions are really rough, there is a discontinuity for every integer value because of the case vertical == vertical.floor and its division trough zero. so ive implemented another Select.ar with BinaryOpUGen('==', vertical, vertical.floor. i think when this condition is met the signal should be rendered as a normal cosine, because no anti-aliasing is needed.
but this is probably wrong, because now the signal is not rendered as a smooth full-cycle sinusoid when the phase is inside an incomplete period any more. any ideas?

(
{
	arg freq = 392;
	var horizontal = \horizontal.kr(0.80);
	var vertical = \vertical.kr(2.2);
	var cos, phasor;

	phasor = LFSaw.ar(freq/2,1).range(horizontal.neg, 1-horizontal);

	phasor = phasor.bilin(0, horizontal.neg, 1-horizontal, vertical, 0, 1);
	cos = Select.ar(phasor > vertical.floor,
		[
			(phasor * 2pi).cos.neg,
			Select.ar(BinaryOpUGen('==', vertical, vertical.floor),
				[
					(phasor * 2pi).cos.neg,
					((phasor.wrap(0,1)/(vertical-vertical.floor)*pi).cos*(vertical-vertical.floor)).neg-(vertical.ceil-vertical)
				]
			);
		]
	);
}.plot
)

EDIT: i tried the crossfade attempt once more because i couldnt figure out how to solve the case vertical = vertical.floor, the result is smooth for sweeping the vertical value but i dont know if its correct and it probably just fixes the vertical value, the aliasing is still prominent for extreme horizontal values.

(
~nearest_even = {|val|
	var val_floor, val_ceil, res, distance;
	val_floor = val.floor;
	val_ceil = val.ceil;
	res = Select.ar (val % 2,
		[ val_floor, val_ceil ],
	);
	distance = (val - res).abs;
	[res, distance];
};

~nearest_odd = {|val|
	var val_floor, val_ceil, res, distance;
	val_floor = val.floor;
	val_ceil = val.ceil;
	res = Select.ar (val + 1 % 2,
		[ val_floor, val_ceil ],
	);
	distance = (val - res).abs;
	[res, distance];
};
)

(
{
	arg out=0, pan=0, amp=0.25, freq=110;

	var horizontal = MouseX.kr(0.01,0.99);
	var vertical = K2A.ar(MouseY.kr(1.0,10.0));

	var vertical_even = ~nearest_even.(vertical);
	var vertical_odd = ~nearest_odd.(vertical);
	var cos, phasor, sig;

	vertical = [vertical_even[0], vertical_odd[0]];

	phasor = Phasor.ar(0, freq/2 * SampleDur.ir, horizontal.neg, 1-horizontal, horizontal.neg);
	phasor = phasor.bilin(0, horizontal.neg, 1-horizontal, vertical, 0, 1);

	cos = (phasor * 2pi).cos.neg;

	sig = XFade2.ar(cos[0], cos[1], vertical_even[1] * 2 - 1);

	sig = LeakDC.ar(sig);
	sig = Pan2.ar(sig, pan, amp);
	Out.ar(out, sig);
}.scope;
)

s.freqscope;

EDIT: the Phython Code from the Authors says something like this:

f0 = 500.
fs = 44100.
w0 = 2*pi*f0/fs
N = int(fs/f0)
t = arange(0,44100)
T = f0/fs
P = 1/T

d = 0.80
v = 2.20

# -- phase distortion function
def vps(x,d,v, suppress):
if x < d: p = (v*x)/d
else: p = (1-v)*(x-d)/(1-d) + v
# aliasing reduction
c1 = c2 = 0
if suppress:
if p > int(v):
c = v % 1
if 0 < c and c <= 0.5:
p = 0.5 * (p % 1) / c
c1 = 0.5 * (1 - cos(2*pi*c))
c2 = c1-1
else:
p = (p % 1) / c
if p > 0.5:
c1 = 0.5 * (1 + cos(2*pi*c))
c2 = 1-c1
return p,c1,c2

# -- signal generation
def process(d,v, suppress):
y = zeros(len(t))
x = zeros(len(t))
phi = 0
for n in range(0,len(t)):
p,c1,c2 = vps(phi,d,v, suppress)
y[n] = -cos(2*pi*p) # waveshaping
x[n] = p
if c1 != 0:
y[n] = y[n]*c1 + c2
phi += T
if phi > 1: phi -= 1
return y,x

# -- spectrum
def spectrum(s):
NFFT = 16384*2
NFFT2 = 16384
NWIN = 16384
win = chebwin(NWIN, 120)
win = append(win, zeros(NFFT-NWIN))
scal = NFFT*sqrt(mean(win**2))
spec = fft(win*s[0:NFFT])
mags = sqrt(spec[0:NFFT2].real**2 + spec[0:NFFT2].imag**2)
norm = 20*log10(mags/scal)
spec = norm - max(norm)
return spec


# -- main
y1,x1 = process(d,v, False)
y2,x2 = process(d,v, True)