public static function checkSolution(array $solution, array $task = null)
    {
        if(!self::checkInput($solution))
        {
            throw new \InvalidArgumentException('Input is no Sudoku array.');
        }

        $dim = count($solution);

        if($task !== null)
        {
            if(count($task) !== $dim)
                return false;

            for($i = 0; $i < $dim; $i++)
            {
                for($j = 0; $j < $dim; $j++)
                {
                    if($task[$i][$j] !== null && $solution[$i][$j] !== $task[$i][$j])
                        return false;
                }
            }
        }


        // check rows
        for($row = 0; $row < $dim; $row++)
        {
            $valueFound = array_fill(1,$dim,false);
            for($col = 0; $col < $dim; $col++)
            {
                // null check is only needed here
                if($solution[$row][$col] === null || $valueFound[$solution[$row][$col]] === true)
                    return false;
                else
                    $valueFound[$solution[$row][$col]] = true;
            }
        }

        // check columns
        for($col = 0; $col < $dim; $col++)
        {
            $valueFound = array_fill(1,$dim,false);
            for($row = 0; $row < $dim; $row++)
            {
                if($valueFound[$solution[$row][$col]] === true)
                    return false;
                else
                    $valueFound[$solution[$row][$col]] = true;
            }
        }

        // check blocks
        $blockSize = self::$blockSizes[$dim];
        for($row = 0; $row < $dim; $row += $blockSize)
        {
            for($col = 0; $col < $dim; $col += $blockSize)
            {
                $valueFound = array_fill(1,$dim,false);
                for($blockRow = 0; $blockRow < $blockSize;$blockRow++)
                {
                    for($blockCol = 0; $blockCol < $blockSize;$blockCol++)
                    {
                        if($valueFound[$solution[$row+$blockRow][$col+$blockCol]] === true)
                            return false;
                        else
                            $valueFound[$solution[$row+$blockRow][$col+$blockCol]] = true;
                    }
                }
            }
        }

        return true;
    }