public function zRelations($usecached = true) {
		// this is a fairly expensive calculation, so by default we'll use this cached array that we calculated earlier using the algorithm below
		if ($usecached) {
			include(__DIR__.'/../cache/zmates.cache.php');
			if (array_key_exists($this->primeFormRing($this->bits), $zmates)) {
				return $zmates[$this->bits];
			}
			return null;
		}

		// if not using the cached calculations, we'll do this the serious brute force way with a couple of optimizations
		$countOnBits = \ianring\BitmaskUtils::countOnBits($this->bits);

		// we can omit any that are too small to have the required number of bits on, for example if the set has a cardinality
		// of 6, the minimum value it can have is 111111 (63). That's always 2^n-1
		$minimum = pow(2, $countOnBits) - 1;

		$same = array();
		$all = range($minimum, 4095);
		foreach ($all as $s) {
			// for every set in the power set, we perform some exclusions in the order of least to most complexity

			// a z-mate will have the same pitch cardinality. If this one doesn't, keep looking
			if (\ianring\BitmaskUtils::countOnBits($s) != $countOnBits) {
				continue;
			}

			// a z-mate will not be a rotation,
			if (\ianring\BitmaskUtils::isRotationOf($this->bits, $s)) {
				continue;
			}

			// a z-mate will not be a rotation of an inversion either
			$invertedS = \ianring\BitmaskUtils::reflectBitmask($s);
			if (\ianring\BitmaskUtils::isRotationOf($this->bits, $invertedS)) {
				continue;
			}

			// we only return the prime of the z-mate, so we can discard all non-primes
			if (!self::isPrime($s)) {
				continue;
			}

			// very few candidates will reach this point, so for those we can do the more expensive calculation of interval vectors
			$p = new PitchClassSet($s);
			$i = $p->intervalVector();
			$intervals = $this->intervalVector();
			// to compare the content of two arrays it's really easy to squash them into strings and compare those
			if (json_encode($i) == json_encode($intervals)) {
				$same[] = $s;
			}
		}

		return $same;

	}
public function zRelations($usecached = true) {
		// this is a fairly expensive calculation, so by default we'll use this cached array that we calculated earlier using the algorithm below
		if ($usecached) {
			include(__DIR__.'/../cache/zmates.cache.php');
			if (array_key_exists($this->primeFormRing($this->bits), $zmates)) {
				return $zmates[$this->bits];
			}
			return null;
		}

		// if not using the cached calculations, we'll do this the serious brute force way with a couple of optimizations
		$countOnBits = \ianring\BitmaskUtils::countOnBits($this->bits);

		// we can omit any that are too small to have the required number of bits on, for example if the set has a cardinality
		// of 6, the minimum value it can have is 111111 (63). That's always 2^n-1
		$minimum = pow(2, $countOnBits) - 1;

		$same = array();
		$all = range($minimum, 4095);
		foreach ($all as $s) {
			// for every set in the power set, we perform some exclusions in the order of least to most complexity

			// a z-mate will have the same pitch cardinality. If this one doesn't, keep looking
			if (\ianring\BitmaskUtils::countOnBits($s) != $countOnBits) {
				continue;
			}

			// a z-mate will not be a rotation,
			if (\ianring\BitmaskUtils::isRotationOf($this->bits, $s)) {
				continue;
			}

			// a z-mate will not be a rotation of an inversion either
			$invertedS = \ianring\BitmaskUtils::reflectBitmask($s);
			if (\ianring\BitmaskUtils::isRotationOf($this->bits, $invertedS)) {
				continue;
			}

			// we only return the prime of the z-mate, so we can discard all non-primes
			if (!self::isPrime($s)) {
				continue;
			}

			// very few candidates will reach this point, so for those we can do the more expensive calculation of interval vectors
			$p = new PitchClassSet($s);
			$i = $p->intervalVector();
			$intervals = $this->intervalVector();
			// to compare the content of two arrays it's really easy to squash them into strings and compare those
			if (json_encode($i) == json_encode($intervals)) {
				$same[] = $s;
			}
		}

		return $same;

	}
public function zRelations ( $ usecached = true ) { // this is a fairly expensive calculation, so by default we'll use this cached array that we calculated earlier using the algorithm below if ( $ usecached ) { include ( __DIR__ . '/../cache/zmates.cache.php' ) ; if ( array_key_exists ( $ this -> primeFormRing ( $ this -> bits ) , $ zmates ) ) { return $ zmates [ $ this -> bits ] ; } return null ; } // if not using the cached calculations, we'll do this the serious brute force way with a couple of optimizations $ countOnBits = \ ianring \ BitmaskUtils :: countOnBits ( $ this -> bits ) ; // we can omit any that are too small to have the required number of bits on, for example if the set has a cardinality // of 6, the minimum value it can have is 111111 (63). That's always 2^n-1 $ minimum = pow ( 2 , $ countOnBits ) - 1 ; $ same = array ( ) ; $ all = range ( $ minimum , 4095 ) ; foreach ( $ all as $ s ) { // for every set in the power set, we perform some exclusions in the order of least to most complexity // a z-mate will have the same pitch cardinality. If this one doesn't, keep looking if ( \ ianring \ BitmaskUtils :: countOnBits ( $ s ) != $ countOnBits ) { continue ; } // a z-mate will not be a rotation, if ( \ ianring \ BitmaskUtils :: isRotationOf ( $ this -> bits , $ s ) ) { continue ; } // a z-mate will not be a rotation of an inversion either $ invertedS = \ ianring \ BitmaskUtils :: reflectBitmask ( $ s ) ; if ( \ ianring \ BitmaskUtils :: isRotationOf ( $ this -> bits , $ invertedS ) ) { continue ; } // we only return the prime of the z-mate, so we can discard all non-primes if ( ! self :: isPrime ( $ s ) ) { continue ; } // very few candidates will reach this point, so for those we can do the more expensive calculation of interval vectors $ p = new PitchClassSet ( $ s ) ; $ i = $ p -> intervalVector ( ) ; $ intervals = $ this -> intervalVector ( ) ; // to compare the content of two arrays it's really easy to squash them into strings and compare those if ( json_encode ( $ i ) == json_encode ( $ intervals ) ) { $ same [ ] = $ s ; } } return $ same ; }
When two prime forms have the same internal vector, and when one can not be reduced to the other
by inversion or transposition, they are said to be "Z-Related".

This function will accept any set, whether it is prime or not. But it will only return the prime z-mate.

Z-related sets are always in pairs. Isn't that interesting? That is a consequence of the 12-TET system. In other tuning systems,
Z-mates can occur in different groupings.

@see  https://en.wikipedia.org/wiki/Interval_vector#Z-relation
@return int
When two prime forms have the same internal vector and when one can not be reduced to the other by inversion or transposition they are said to be Z - Related .