UGens output value to function?

Hi James,
thanks for the remarks! The example written in the thread dragged along some components while being modified and rendering them unnecessary indeed…
The lower2Pow variable you’ve proposed seems to be doing the trick, thanks so much for the concise formula!
Jan

I realized later that it could be tightened down even further – in the end, you only need the fractional part of log2.

To derive it step by step:

x / (2 ** floor(log2(x))) – division is a relatively slow operation, so I thought about how to remove it. The identity log(a / b) == log(a) - log(b) does this. In the general case, taking two logarithms instead of one wouldn’t be more efficient – but here, “b” is a power-of – log2(2 ** x) == x so the first transformation is an efficiency gain (if you save log2(x) in a variable):

x / (2 ** floor(log2(x)))
= 2 ** (log2(x) - floor(log2(x)))

Then, a - floor(a) is just frac(a)!

= 2 ** frac(log2(x))  // replaces the whole other formula

Testing – there is a little floating point rounding error between the first and second versions, but the second and third are completely equivalent:

f = { |x| x / (2 ** floor(log2(x))) };
g = { |x| var l2 = log2(x); 2 ** (l2 - l2.floor) };
h = { |x| 2 ** frac(log2(x)) };

~test = {
	var x = 100.0.rand;
	var y = [f.(x), g.(x), h.(x)];
	y.doAdjacentPairs { |a, b|
		(a absdif: b).debug("difference");
	};
};

~test.value;

difference: 2.2204460492503e-16
difference: 0.0
-> [ 1.0050222277641, 1.0050222277641, 1.0050222277641 ]

hjh

2 Likes

Amazing, thanks @jamshark70 for the lesson in code elegance and efficiency!