//
//	cliprnd.cs
//
//	乱数
//
//	CLiP - Common Library for P/ECE
//	Copyright (C) 2017 Naoyuki Sawa
//
//	* Mon Apr 10 21:37:40 JST 2017 Naoyuki Sawa
//	- 1st リリース。
//	  C言語版のcliprnd.cの関数の内、今回は「ユーティリティ：シャフル」だけ実装しました。
//	  C#ではSystem.Randomの乱数で充分なので、cliprnd.cの他の関数は実装しなくても良いような気がしますが、
//	  もし今後、Cソースからの移植の都合等で他の関数も必要になったら、その時にcliprnd.cの他の関数も実装しようと思います。
//
using System;
namespace org.piece_me {
	public static partial class libclip {
		//*****************************************************************************
		//	ユーティリティ：シャフル
		//*****************************************************************************
		//C言語版のshuffle()に互換なバージョンです。(cliprnd.cを参照して下さい。)
		public static void shuffle(VoidPtr _base, int num, int width, System.Random seed) {
			//交換先要素は、配列の先頭要素から、配列の(最終要素-1)まで。
			BytePtr p_dst = _base;
			while(num > 1) {
				//交換元要素は、交換先要素から、配列の最終要素まで。
				BytePtr p_src = p_dst + (seed.Next(num) * width);
				//交換先要素と、交換元要素を、一文字づつ交換します。
				for(int i = 0; i < width; i++) {
					byte c = p_src[0];
					         p_src.Write(p_dst[0]);
					                     p_dst.Write(c);
				}
				//交換先要素の、残り数を減らします。
				num--;
			}
		}
		//-----------------------------------------------------------------------------
		//C#版特有のバージョンです。主に、ポインタ配列のシャフルを想定しています。
		public static void shuffle<T>(GenericPtr<T> _base, int num, System.Random seed) {
			shuffle(_base.Array, _base.Offset, num, seed);
		}
		//-----------------------------------------------------------------------------
		//C#版特有のバージョンです。配列全体をシャフルします。
		public static void shuffle<T>(T[] array, System.Random seed) {
			shuffle(array, 0, array.Length, seed);
		}
		//-----------------------------------------------------------------------------
		//C#版特有のバージョンです。配列の指定された範囲をシャフルします。
		public static void shuffle<T>(T[] array, int index, int length, System.Random seed) {
			//交換先要素は、arrayp[index]から、arrayp[index+length-2]まで。
			int i_dst = index;
			while(length > 1) {
				//交換元要素は、交換先要素から、arrayp[index+length-1]まで。
				int i_src = i_dst + seed.Next(length);
				//交換先要素と、交換元要素を、交換します。
				XCHG(ref array[i_dst], ref array[i_src]);
				//交換先要素を、次へ進めます。
				i_dst++;
				//交換先要素の、残り数を減らします。
				length--;
			}
		}
	}
}
