Iteration question

hey,
im working on a function for creating n-size hadamard matrices (instead of storing them all in a dictionary).
i think i got the formula already.
but i would like to type in ~getHadamard.(2) for a 2x2 matrix, ~getHadamard.(4) for a 4x4 matrix, ~getHadamard.(n) for a nxn matrix. does somebody know how to adjust n so the function is giving the desired result? if i type in ~getHadamard.(2) or ~getHadamard.(4) the result seems correct.
but for ~getHadamard.(8) the matrix.size = 16 not 8. thanks :slight_smile:

still having a hard time with iteration. here is the code:

(
~getHadamard = { |order|
	var h2, kronecker, matrix, n;

	n = order.log2 - 1;

	h2 = [
		[ 1,  1 ],
		[ 1, -1 ]
	];

	kronecker = { |a, b|
		a.collect { |x|
			x.collect { |y| b * y }.reduce('+++')
		}.reduce('++')
	};

// iteration attempt
	n.do{ |i|
		var matrix = h2;
		h2 = kronecker.(matrix, h2);
		h2 = h2 * sqrt(order).reciprocal;
	};
	matrix = h2;
/*
	matrix = h2;
	matrix = matrix * sqrt(2).reciprocal;

	matrix = kronecker.(matrix, h2);
	matrix = matrix * sqrt(2).reciprocal;

	matrix = kronecker.(matrix, h2);
	matrix = matrix * sqrt(2).reciprocal;

	matrix = kronecker.(matrix, h2);
	matrix = matrix * sqrt(2).reciprocal;

	matrix = kronecker.(matrix, h2);
	matrix = matrix * sqrt(2).reciprocal;
*/
};

~hadamard = ~getHadamard.(2); // type in 2 for 2x2, 4 for 4x4, 8 for 8x8, 16 for 16x16
)

okay, the size is now correct.

but the multiplication with sqrt(2).reciprocal still wrong… lets see:

(
~getHadamard = { |order|
	var h2, kronecker, matrix, n;

	n = order.log2 - 1;

	h2 = [
		[ 1,  1 ],
		[ 1, -1 ]
	];

	kronecker = { |a, b|
		a.collect { |x|
			x.collect { |y| b * y }.reduce('+++')
		}.reduce('++')
	};

	matrix = h2;

	n.do{
		matrix = kronecker.(matrix, h2);
		matrix = matrix * sqrt(order).reciprocal;
		matrix.postln;
	};
	matrix;
};

~hadamard = ~getHadamard.(8);
)

Is it necessary at all to multiply within the loop?

If you take matrix = matrix * sqrt(order).reciprocal; outside of n.do then you get a matrix of +/- 1.

If you take this result and multiply by the desired final magnitude, then you get what you want with less work (and less complication = less debugging).

Otherwise, if you really want to do it this way, consider that the final result of multiplying +/-1 by sqrt(order).reciprocal /n/ times is to multiply by sqrt(order).reciprocal ** n.

Algebra again:

sqrt(order).reciprocal ** n

(order ** (1/2)).reciprocal ** n
((order ** (1/2)) ** -1) ** n  // and now multiply exponents

order ** (n.neg/2)

// If order = 8, n = log2(8) - 1 = 2 so
8 ** (-2/2) == 8 ** (-1) == 0.125

If that’s not what you want, then the iterative formula needs to change.

hjh

hey, putting the multiplication outside of the loop is the solution.
thanks a lot for your help :slight_smile:

(
~getHadamard = { |order|
	var h2, kronecker, matrix, n;

	n = order.log2 - 1;

	h2 = [
		[ 1,  1 ],
		[ 1, -1 ]
	];

	kronecker = { |a, b|
		a.collect { |x|
			x.collect { |y| b * y }.reduce('+++')
		}.reduce('++')
	};

	matrix = h2;

	n.do{
		matrix = kronecker.(matrix, h2);
	};
	matrix = matrix * sqrt(order).reciprocal;
};

~hadamard = ~getHadamard.(2);
)