function [ Y_predict accuracies ] = svm( X_train, X_test, Y_train, Y_test, kernel, rangeC, rangeG )

    % kernel : 1 = linear, 2 = rbf

    %X_train = X_train';
    %X_test = X_test';
    
    maxaccuracy = 0.0;
    
    if kernel == 1      % linear kernel
        
        % find the best parameter through cross validation
        is_dist_train = zeros( size( X_train, 2 ), size( X_train, 2 ) );
        for i = 1 : size( X_train, 2 )
            is_dist_train(i,:) = 1-sum( min( X_train, repmat( X_train(:,i), [ 1 size(X_train,2) ] ) ) );
        end        

        is_dist_test = zeros( size( X_test, 2 ), size( X_train, 2 ) );
        for i = 1 : size( X_train, 2 )
            is_dist_test(:,i) = 1-sum( min( X_test, repmat( X_train(:,i), [ 1 size(X_test,2) ] ) ) )';
        end

        count = 0;
        accuracies = zeros( 1, length( rangeG ) * length( rangeC ) );
        for i = 1 : length( rangeG )
            feature_train = [ (1:size( X_train, 2 ))' exp(-is_dist_train/10^rangeG(i)) ];
            feature_test = [ (1:size( X_test, 2 ))' exp(-is_dist_test/10^rangeG(i)) ];
            feature_train = X_train';
            feature_test = X_test';

            for j = 1 : length( rangeC )
                option = sprintf( '-t 0 -c %f -q', 2^rangeC( j ) );
                model = svmtrain( Y_train, feature_train, option );
                [ Y_predict, accuracy ] = svmpredict( Y_test, feature_test, model );
                %fprintf( 1, '%0.1f ', accuracy(1) );
                count = count + 1;
                accuracies(count) = accuracy(1);
            end
        end
            %fprintf( 1, '\n' );

    elseif kernel == 2      % rbf kernel
        
        % find the best parameters through cross validation
        maxpowerC = 0;
        maxpowerg = 0;
        powerCrange = 5 : 15;
        powergrange = -15 : 2;
        accuracies_validation = zeros( length( powerCrange ), length( powergrange ) );
        accuracies_test = zeros( length( powerCrange ), length( powergrange ) );
        
        for k = 1 : validationsetnum
            for i = 1 : length( powerCrange )
                powerC = powerCrange( i );
                for j = 1 : length( powergrange )
                    powerg = powergrange( j );
                    option = sprintf( '-c %f -g %f -q', 2 ^ powerC, 2 ^ powerg );
                    model = svmtrain( Y_validation{ k }( 1 : trainsize_validation ), X_validation{ k }( 1 : trainsize_validation, : ), option );
                    [ predict_label, accuracy ] = svmpredict( Y_validation{ k }( trainsize_validation + 1 : end ), X_validation{ k }( trainsize_validation + 1 : end, : ), model );
                    accuracies_validation( i, j ) = accuracies_validation( i, j ) + accuracy( 1 );                
                    model = svmtrain( Y_test( 1 : trainsize_test ), X_test( 1 : trainsize_test, : ), option );
                    [ predict_label, accuracy ] = svmpredict( Y_test( trainsize_test + 1 : end ), X_test( trainsize_test + 1 : end, : ), model );
                    accuracies_test( i, j ) = accuracies_test( i, j ) + accuracy( 1 );
                end
            end
        end
        %accuracies_validation = accuracies_validation / validationsetnum;
        accuracies_validation = conv2( accuracies_validation, ones( 5 ), 'valid' ) / 25 / validationsetnum;
        accuracies_test = accuracies_test / validationsetnum;
        [ temp maxposi_row ] = max( accuracies_validation );
        [ accuracy_validation maxposi_col ] = max( temp );
        maxpowerC = powerCrange( maxposi_row( maxposi_col ) + 2 );
        maxpowerg = powergrange( maxposi_col + 2 );
        
        % training & testing with the best parameter
        option = sprintf( '-c %f -g %f', 2 ^ maxpowerC, 2 ^ maxpowerg );
        model = svmtrain( Y_test( 1 : trainsize_test ), X_test( 1 : trainsize_test, : ), option );
        [ predict_label, accuracy ] = svmpredict( Y_test( trainsize_test + 1 : end ), X_test( trainsize_test + 1 : end, : ), model );
    
        accuracy_test = accuracy( 1 );
        if echooff == 0
            fprintf( 1, 'powerC = %d, powerg = %d, training accuracy = %f, test accuracy = %f\n', maxpowerC, maxpowerg, accuracy_validation, accuracy_test );
        end
        
        maxaccuracy = max( accuracies_test(:) );
    else
        accuracy_validation = 0;
        accuracy_test = 0;
    end