// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains CRC32 algorithms that are not specific to any architecture
// and don't use hardware acceleration.
//
// The simple (and slow) CRC32 implementation only uses a 256*4 bytes table.
//
// The slicing-by-8 algorithm is a faster implementation that uses a bigger
// table (8*256*4 bytes).

package crc32

import 

// simpleMakeTable allocates and constructs a Table for the specified
// polynomial. The table is suitable for use with the simple algorithm
// (simpleUpdate).
func simpleMakeTable( uint32) *Table {
	 := new(Table)
	simplePopulateTable(, )
	return 
}

// simplePopulateTable constructs a Table for the specified polynomial, suitable
// for use with simpleUpdate.
func simplePopulateTable( uint32,  *Table) {
	for  := 0;  < 256; ++ {
		 := uint32()
		for  := 0;  < 8; ++ {
			if &1 == 1 {
				 = ( >> 1) ^ 
			} else {
				 >>= 1
			}
		}
		[] = 
	}
}

// simpleUpdate uses the simple algorithm to update the CRC, given a table that
// was previously computed using simpleMakeTable.
func simpleUpdate( uint32,  *Table,  []byte) uint32 {
	 = ^
	for ,  := range  {
		 = [byte()^] ^ ( >> 8)
	}
	return ^
}

// Use slicing-by-8 when payload >= this value.
const slicing8Cutoff = 16

// slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm.
type slicing8Table [8]Table

// slicingMakeTable constructs a slicing8Table for the specified polynomial. The
// table is suitable for use with the slicing-by-8 algorithm (slicingUpdate).
func slicingMakeTable( uint32) *slicing8Table {
	 := new(slicing8Table)
	simplePopulateTable(, &[0])
	for  := 0;  < 256; ++ {
		 := [0][]
		for  := 1;  < 8; ++ {
			 = [0][&0xFF] ^ ( >> 8)
			[][] = 
		}
	}
	return 
}

// slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a
// table that was previously computed using slicingMakeTable.
func slicingUpdate( uint32,  *slicing8Table,  []byte) uint32 {
	if len() >= slicing8Cutoff {
		 = ^
		for len() > 8 {
			 ^= byteorder.LeUint32()
			 = [0][[7]] ^ [1][[6]] ^ [2][[5]] ^ [3][[4]] ^
				[4][>>24] ^ [5][(>>16)&0xFF] ^
				[6][(>>8)&0xFF] ^ [7][&0xFF]
			 = [8:]
		}
		 = ^
	}
	if len() == 0 {
		return 
	}
	return simpleUpdate(, &[0], )
}