<commit_before>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "harness/compat.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "procs.h"

const char *kernel_code =
"__kernel void test_kernel(\n"
"char%s c, uchar%s uc, short%s s, ushort%s us, int%s i, uint%s ui, float%s f,\n"
"__global float%s *result)\n"
"{\n"
"  result[0] = %s(c);\n"
"  result[1] = %s(uc);\n"
"  result[2] = %s(s);\n"
"  result[3] = %s(us);\n"
"  result[4] = %s(i);\n"
"  result[5] = %s(ui);\n"
"  result[6] = f;\n"
"}\n";

const char *kernel_code_long =
"__kernel void test_kernel_long(\n"
"long%s l, ulong%s ul,\n"
"__global float%s *result)\n"
"{\n"
"  result[0] = %s(l);\n"
"  result[1] = %s(ul);\n"
"}\n";

int test_parameter_types_long(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
{
  clMemWrapper results;
  int error;
  size_t global[3] = {1, 1, 1};
  float results_back[2*16];
  int count, index;
  const char* types[] = { "long", "ulong" };
  char kernel_string[8192];
  int sizes[] = {1, 2, 4, 8, 16};
  const char* size_strings[] = {"", "2", "4", "8", "16"};
  float expected;
  int total_errors = 0;
  int size_to_test;
  char *ptr;
  char convert_string[1024];
  size_t max_parameter_size;

  // We don't really care about the contents since we're just testing that the types work.
  cl_long l[16]={-21,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15};
  cl_ulong ul[16]={22,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

  // Calculate how large our paramter size is to the kernel
  size_t parameter_size = sizeof(cl_long) + sizeof(cl_ulong);

  // Init our strings.
  kernel_string[0] = '\0';
  convert_string[0] = '\0';

  // Get the maximum parameter size allowed
  error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL );
    test_error( error, "Unable to get max parameter size from device" );

  // Create the results buffer
  results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*2*16, NULL, &error);
  test_error(error, "clCreateBuffer failed");

  // Go over all the vector sizes
  for (size_to_test = 0; size_to_test < 5; size_to_test++) {
    clProgramWrapper program;
    clKernelWrapper kernel;

    size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem);
    if (total_parameter_size > max_parameter_size) {
      log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n",
               (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size);
      continue;
    }

    log_info("Testing vector size %d\n", sizes[size_to_test]);

    // If size is > 1, then we need a explicit convert call.
    if (sizes[size_to_test] > 1) {
      sprintf(convert_string, "convert_float%s",  size_strings[size_to_test]);
    } else {
      sprintf(convert_string, " ");
    }

    // Build the kernel
    sprintf(kernel_string, kernel_code_long,
            size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test],
            convert_string, convert_string
    );

    ptr = kernel_string;
    error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel_long");
    test_error(error, "create single kernel failed");

    // Set the arguments
    for (count = 0; count < 2; count++) {
      switch (count) {
        case 0: error = clSetKernelArg(kernel, count, sizeof(cl_long)*sizes[size_to_test], &l); break;
        case 1: error = clSetKernelArg(kernel, count, sizeof(cl_ulong)*sizes[size_to_test], &ul); break;
        default: log_error("Test error"); break;
      }
      if (error)
        log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]);
      test_error(error, "clSetKernelArgs failed");
    }
    error = clSetKernelArg(kernel, 2, sizeof(cl_mem), &results);
    test_error(error, "clSetKernelArgs failed");

    // Execute
    error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL);
    test_error(error, "clEnqueueNDRangeKernel failed");

    // Read back the results
    error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*2*16, results_back, 0, NULL, NULL);
    test_error(error, "clEnqueueReadBuffer failed");

    // Verify the results
    for (count = 0; count < 2; count++) {
      for (index=0; index < sizes[size_to_test]; index++) {
        switch (count) {
          case 0: expected = (float)l[index]; break;
          case 1: expected = (float)ul[index]; break;
          default: log_error("Test error"); break;
        }

        if (results_back[count*sizes[size_to_test]+index] != expected) {
          total_errors++;
          log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test],
                    index, results_back[count*sizes[size_to_test]+index], expected);
        }
      }
    }
  }

  return total_errors;
}

int test_parameter_types(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
{
  clMemWrapper results;
  int error;
  size_t global[3] = {1, 1, 1};
  float results_back[7*16];
  int count, index;
  const char* types[] = {"char", "uchar", "short", "ushort", "int", "uint", "float"};
  char kernel_string[8192];
  int sizes[] = {1, 2, 4, 8, 16};
  const char* size_strings[] = {"", "2", "4", "8", "16"};
  float expected;
  int total_errors = 0;
  int size_to_test;
  char *ptr;
  char convert_string[1024];
  size_t max_parameter_size;

  // We don't really care about the contents since we're just testing that the types work.
  cl_char c[16]={0,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15};
  cl_uchar uc[16]={16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  cl_short s[16]={-17,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15};
  cl_ushort us[16]={18,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  cl_int i[16]={-19,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15};
  cl_uint ui[16]={20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  cl_float f[16]={-23,-1,2,-3,4,-5,6,-7,8,-9,10,-11,12,-13,14,-15};

  // Calculate how large our paramter size is to the kernel
  size_t parameter_size = sizeof(cl_char) + sizeof(cl_uchar) +
  sizeof(cl_short) +sizeof(cl_ushort) +
  sizeof(cl_int) +sizeof(cl_uint) +
  sizeof(cl_float);

  // Init our strings.
  kernel_string[0] = '\0';
  convert_string[0] = '\0';

  // Get the maximum parameter size allowed
  error = clGetDeviceInfo( device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof( max_parameter_size ), &max_parameter_size, NULL );
    test_error( error, "Unable to get max parameter size from device" );

  // Create the results buffer
  results = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float)*7*16, NULL, &error);
  test_error(error, "clCreateBuffer failed");

  // Go over all the vector sizes
  for (size_to_test = 0; size_to_test < 5; size_to_test++) {
    clProgramWrapper program;
    clKernelWrapper kernel;

    size_t total_parameter_size = parameter_size*sizes[size_to_test] + sizeof(cl_mem);
    if (total_parameter_size > max_parameter_size) {
      log_info("Can not test with vector size %d because it would exceed the maximum allowed parameter size to the kernel. (%d > %d)\n",
               (int)sizes[size_to_test], (int)total_parameter_size, (int)max_parameter_size);
      continue;
    }

    log_info("Testing vector size %d\n", sizes[size_to_test]);

    // If size is > 1, then we need a explicit convert call.
    if (sizes[size_to_test] > 1) {
      sprintf(convert_string, "convert_float%s",  size_strings[size_to_test]);
    } else {
      sprintf(convert_string, " ");
    }

    // Build the kernel
    sprintf(kernel_string, kernel_code,
            size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test],
            size_strings[size_to_test], size_strings[size_to_test], size_strings[size_to_test],
            size_strings[size_to_test], size_strings[size_to_test],
            convert_string, convert_string, convert_string,
            convert_string, convert_string, convert_string
    );

    ptr = kernel_string;
    error = create_single_kernel_helper(context, &program, &kernel, 1, (const char **)&ptr, "test_kernel");
    test_error(error, "create single kernel failed");

    // Set the arguments
    for (count = 0; count < 7; count++) {
      switch (count) {
        case 0: error = clSetKernelArg(kernel, count, sizeof(cl_char)*sizes[size_to_test], &c); break;
        case 1: error = clSetKernelArg(kernel, count, sizeof(cl_uchar)*sizes[size_to_test], &uc); break;
        case 2: error = clSetKernelArg(kernel, count, sizeof(cl_short)*sizes[size_to_test], &s); break;
        case 3: error = clSetKernelArg(kernel, count, sizeof(cl_ushort)*sizes[size_to_test], &us); break;
        case 4: error = clSetKernelArg(kernel, count, sizeof(cl_int)*sizes[size_to_test], &i); break;
        case 5: error = clSetKernelArg(kernel, count, sizeof(cl_uint)*sizes[size_to_test], &ui); break;
        case 6: error = clSetKernelArg(kernel, count, sizeof(cl_float)*sizes[size_to_test], &f); break;
        default: log_error("Test error"); break;
      }
      if (error)
        log_error("Setting kernel arg %d %s%s: ", count, types[count], size_strings[size_to_test]);
      test_error(error, "clSetKernelArgs failed");
    }
    error = clSetKernelArg(kernel, 7, sizeof(cl_mem), &results);
    test_error(error, "clSetKernelArgs failed");

    // Execute
    error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0, NULL, NULL);
    test_error(error, "clEnqueueNDRangeKernel failed");

    // Read back the results
    error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0, sizeof(cl_float)*7*16, results_back, 0, NULL, NULL);
    test_error(error, "clEnqueueReadBuffer failed");

    // Verify the results
    for (count = 0; count < 7; count++) {
      for (index=0; index < sizes[size_to_test]; index++) {
        switch (count) {
          case 0: expected = (float)c[index]; break;
          case 1: expected = (float)uc[index]; break;
          case 2: expected = (float)s[index]; break;
          case 3: expected = (float)us[index]; break;
          case 4: expected = (float)i[index]; break;
          case 5: expected = (float)ui[index]; break;
          case 6: expected = (float)f[index]; break;
          default: log_error("Test error"); break;
        }

        if (results_back[count*sizes[size_to_test]+index] != expected) {
          total_errors++;
          log_error("Conversion from %s%s failed: index %d got %g, expected %g.\n", types[count], size_strings[size_to_test],
                    index, results_back[count*sizes[size_to_test]+index], expected);
        }
      }
    }
  }

  if (gHasLong) {
    log_info("Testing long types...\n");
    total_errors += test_parameter_types_long( device, context, queue, num_elements );
  }
  else {
    log_info("Longs unsupported, skipping.");
  }

  return total_errors;
}

<commit_msg>NFC: clang-format test_basic_parameter_types.cpp (#1151)<commit_after>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "harness/compat.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "procs.h"

const char *kernel_code = R"(
__kernel void test_kernel(
char%s c, uchar%s uc, short%s s, ushort%s us, int%s i, uint%s ui, float%s f,
__global float%s *result)
{
    result[0] = %s(c);
    result[1] = %s(uc);
    result[2] = %s(s);
    result[3] = %s(us);
    result[4] = %s(i);
    result[5] = %s(ui);
    result[6] = f;
})";

const char *kernel_code_long = R"(
__kernel void test_kernel_long(
long%s l, ulong%s ul,
__global float%s *result)
{
    result[0] = %s(l);
    result[1] = %s(ul);
})";

int test_parameter_types_long(cl_device_id device, cl_context context,
                              cl_command_queue queue, int num_elements)
{
    clMemWrapper results;
    int error;
    size_t global[3] = { 1, 1, 1 };
    float results_back[2 * 16];
    int count, index;
    const char *types[] = { "long", "ulong" };
    char kernel_string[8192];
    int sizes[] = { 1, 2, 4, 8, 16 };
    const char *size_strings[] = { "", "2", "4", "8", "16" };
    float expected;
    int total_errors = 0;
    int size_to_test;
    char *ptr;
    char convert_string[1024];
    size_t max_parameter_size;

    // We don't really care about the contents since we're just testing that the
    // types work.
    cl_long l[16] = { -21, -1, 2,  -3,  4,  -5,  6,  -7,
                      8,   -9, 10, -11, 12, -13, 14, -15 };
    cl_ulong ul[16] = { 22, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

    // Calculate how large our paramter size is to the kernel
    size_t parameter_size = sizeof(cl_long) + sizeof(cl_ulong);

    // Init our strings.
    kernel_string[0] = '\0';
    convert_string[0] = '\0';

    // Get the maximum parameter size allowed
    error =
        clGetDeviceInfo(device, CL_DEVICE_MAX_PARAMETER_SIZE,
                        sizeof(max_parameter_size), &max_parameter_size, NULL);
    test_error(error, "Unable to get max parameter size from device");

    // Create the results buffer
    results = clCreateBuffer(context, CL_MEM_READ_WRITE,
                             sizeof(cl_float) * 2 * 16, NULL, &error);
    test_error(error, "clCreateBuffer failed");

    // Go over all the vector sizes
    for (size_to_test = 0; size_to_test < 5; size_to_test++)
    {
        clProgramWrapper program;
        clKernelWrapper kernel;

        size_t total_parameter_size =
            parameter_size * sizes[size_to_test] + sizeof(cl_mem);
        if (total_parameter_size > max_parameter_size)
        {
            log_info(
                "Can not test with vector size %d because it would exceed the "
                "maximum allowed parameter size to the kernel. (%d > %d)\n",
                (int)sizes[size_to_test], (int)total_parameter_size,
                (int)max_parameter_size);
            continue;
        }

        log_info("Testing vector size %d\n", sizes[size_to_test]);

        // If size is > 1, then we need a explicit convert call.
        if (sizes[size_to_test] > 1)
        {
            sprintf(convert_string, "convert_float%s",
                    size_strings[size_to_test]);
        }
        else
        {
            sprintf(convert_string, " ");
        }

        // Build the kernel
        sprintf(kernel_string, kernel_code_long, size_strings[size_to_test],
                size_strings[size_to_test], size_strings[size_to_test],
                convert_string, convert_string);

        ptr = kernel_string;
        error = create_single_kernel_helper(context, &program, &kernel, 1,
                                            (const char **)&ptr,
                                            "test_kernel_long");
        test_error(error, "create single kernel failed");

        // Set the arguments
        for (count = 0; count < 2; count++)
        {
            switch (count)
            {
                case 0:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_long) * sizes[size_to_test],
                        &l);
                    break;
                case 1:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_ulong) * sizes[size_to_test],
                        &ul);
                    break;
                default: log_error("Test error"); break;
            }
            if (error)
                log_error("Setting kernel arg %d %s%s: ", count, types[count],
                          size_strings[size_to_test]);
            test_error(error, "clSetKernelArgs failed");
        }
        error = clSetKernelArg(kernel, 2, sizeof(cl_mem), &results);
        test_error(error, "clSetKernelArgs failed");

        // Execute
        error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0,
                                       NULL, NULL);
        test_error(error, "clEnqueueNDRangeKernel failed");

        // Read back the results
        error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0,
                                    sizeof(cl_float) * 2 * 16, results_back, 0,
                                    NULL, NULL);
        test_error(error, "clEnqueueReadBuffer failed");

        // Verify the results
        for (count = 0; count < 2; count++)
        {
            for (index = 0; index < sizes[size_to_test]; index++)
            {
                switch (count)
                {
                    case 0: expected = (float)l[index]; break;
                    case 1: expected = (float)ul[index]; break;
                    default: log_error("Test error"); break;
                }

                if (results_back[count * sizes[size_to_test] + index]
                    != expected)
                {
                    total_errors++;
                    log_error("Conversion from %s%s failed: index %d got %g, "
                              "expected %g.\n",
                              types[count], size_strings[size_to_test], index,
                              results_back[count * sizes[size_to_test] + index],
                              expected);
                }
            }
        }
    }

    return total_errors;
}

int test_parameter_types(cl_device_id device, cl_context context,
                         cl_command_queue queue, int num_elements)
{
    clMemWrapper results;
    int error;
    size_t global[3] = { 1, 1, 1 };
    float results_back[7 * 16];
    int count, index;
    const char *types[] = { "char", "uchar", "short", "ushort",
                            "int",  "uint",  "float" };
    char kernel_string[8192];
    int sizes[] = { 1, 2, 4, 8, 16 };
    const char *size_strings[] = { "", "2", "4", "8", "16" };
    float expected;
    int total_errors = 0;
    int size_to_test;
    char *ptr;
    char convert_string[1024];
    size_t max_parameter_size;

    // We don't really care about the contents since we're just testing that the
    // types work.
    cl_char c[16] = { 0, -1, 2,  -3,  4,  -5,  6,  -7,
                      8, -9, 10, -11, 12, -13, 14, -15 };
    cl_uchar uc[16] = { 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    cl_short s[16] = { -17, -1, 2,  -3,  4,  -5,  6,  -7,
                       8,   -9, 10, -11, 12, -13, 14, -15 };
    cl_ushort us[16] = {
        18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    };
    cl_int i[16] = { -19, -1, 2,  -3,  4,  -5,  6,  -7,
                     8,   -9, 10, -11, 12, -13, 14, -15 };
    cl_uint ui[16] = { 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    cl_float f[16] = { -23, -1, 2,  -3,  4,  -5,  6,  -7,
                       8,   -9, 10, -11, 12, -13, 14, -15 };

    // Calculate how large our paramter size is to the kernel
    size_t parameter_size = sizeof(cl_char) + sizeof(cl_uchar)
        + sizeof(cl_short) + sizeof(cl_ushort) + sizeof(cl_int)
        + sizeof(cl_uint) + sizeof(cl_float);

    // Init our strings.
    kernel_string[0] = '\0';
    convert_string[0] = '\0';

    // Get the maximum parameter size allowed
    error =
        clGetDeviceInfo(device, CL_DEVICE_MAX_PARAMETER_SIZE,
                        sizeof(max_parameter_size), &max_parameter_size, NULL);
    test_error(error, "Unable to get max parameter size from device");

    // Create the results buffer
    results = clCreateBuffer(context, CL_MEM_READ_WRITE,
                             sizeof(cl_float) * 7 * 16, NULL, &error);
    test_error(error, "clCreateBuffer failed");

    // Go over all the vector sizes
    for (size_to_test = 0; size_to_test < 5; size_to_test++)
    {
        clProgramWrapper program;
        clKernelWrapper kernel;

        size_t total_parameter_size =
            parameter_size * sizes[size_to_test] + sizeof(cl_mem);
        if (total_parameter_size > max_parameter_size)
        {
            log_info(
                "Can not test with vector size %d because it would exceed the "
                "maximum allowed parameter size to the kernel. (%d > %d)\n",
                (int)sizes[size_to_test], (int)total_parameter_size,
                (int)max_parameter_size);
            continue;
        }

        log_info("Testing vector size %d\n", sizes[size_to_test]);

        // If size is > 1, then we need a explicit convert call.
        if (sizes[size_to_test] > 1)
        {
            sprintf(convert_string, "convert_float%s",
                    size_strings[size_to_test]);
        }
        else
        {
            sprintf(convert_string, " ");
        }

        // Build the kernel
        sprintf(kernel_string, kernel_code, size_strings[size_to_test],
                size_strings[size_to_test], size_strings[size_to_test],
                size_strings[size_to_test], size_strings[size_to_test],
                size_strings[size_to_test], size_strings[size_to_test],
                size_strings[size_to_test], convert_string, convert_string,
                convert_string, convert_string, convert_string, convert_string);

        ptr = kernel_string;
        error = create_single_kernel_helper(context, &program, &kernel, 1,
                                            (const char **)&ptr, "test_kernel");
        test_error(error, "create single kernel failed");

        // Set the arguments
        for (count = 0; count < 7; count++)
        {
            switch (count)
            {
                case 0:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_char) * sizes[size_to_test],
                        &c);
                    break;
                case 1:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_uchar) * sizes[size_to_test],
                        &uc);
                    break;
                case 2:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_short) * sizes[size_to_test],
                        &s);
                    break;
                case 3:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_ushort) * sizes[size_to_test],
                        &us);
                    break;
                case 4:
                    error = clSetKernelArg(kernel, count,
                                           sizeof(cl_int) * sizes[size_to_test],
                                           &i);
                    break;
                case 5:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_uint) * sizes[size_to_test],
                        &ui);
                    break;
                case 6:
                    error = clSetKernelArg(
                        kernel, count, sizeof(cl_float) * sizes[size_to_test],
                        &f);
                    break;
                default: log_error("Test error"); break;
            }
            if (error)
                log_error("Setting kernel arg %d %s%s: ", count, types[count],
                          size_strings[size_to_test]);
            test_error(error, "clSetKernelArgs failed");
        }
        error = clSetKernelArg(kernel, 7, sizeof(cl_mem), &results);
        test_error(error, "clSetKernelArgs failed");

        // Execute
        error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global, NULL, 0,
                                       NULL, NULL);
        test_error(error, "clEnqueueNDRangeKernel failed");

        // Read back the results
        error = clEnqueueReadBuffer(queue, results, CL_TRUE, 0,
                                    sizeof(cl_float) * 7 * 16, results_back, 0,
                                    NULL, NULL);
        test_error(error, "clEnqueueReadBuffer failed");

        // Verify the results
        for (count = 0; count < 7; count++)
        {
            for (index = 0; index < sizes[size_to_test]; index++)
            {
                switch (count)
                {
                    case 0: expected = (float)c[index]; break;
                    case 1: expected = (float)uc[index]; break;
                    case 2: expected = (float)s[index]; break;
                    case 3: expected = (float)us[index]; break;
                    case 4: expected = (float)i[index]; break;
                    case 5: expected = (float)ui[index]; break;
                    case 6: expected = (float)f[index]; break;
                    default: log_error("Test error"); break;
                }

                if (results_back[count * sizes[size_to_test] + index]
                    != expected)
                {
                    total_errors++;
                    log_error("Conversion from %s%s failed: index %d got %g, "
                              "expected %g.\n",
                              types[count], size_strings[size_to_test], index,
                              results_back[count * sizes[size_to_test] + index],
                              expected);
                }
            }
        }
    }

    if (gHasLong)
    {
        log_info("Testing long types...\n");
        total_errors +=
            test_parameter_types_long(device, context, queue, num_elements);
    }
    else
    {
        log_info("Longs unsupported, skipping.");
    }

    return total_errors;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <ios>       //std::ios_base::failure
#include <iostream>  //std::cout
#include <stdexcept> //std::invalid_argument std::exception
#include <vector>

#include <adios2.h>

const std::string streamname = "skeleton_stream";

static void printDataStep(const float *data, const size_t start,
                          const size_t count, const int rank, const int step)
{
    std::ofstream myfile;
    std::string filename = "data." + std::to_string(rank);
    if (step == 0)
    {
        myfile.open(filename);
    }
    else
    {
        myfile.open(filename, std::ios::app);
    }

    myfile << "rank=" << rank << " size=" << count << " offsets=" << start
           << " step=" << step << std::endl;

    myfile << " step   row   columns " << start << "..." << start + count - 1
           << std::endl;
    myfile << "        ";
    for (int j = 0; j < count; j++)
    {
        myfile << std::setw(9) << start + j;
    }
    myfile << std::endl;
    myfile << "------------------------------------------------------------"
              "--\n";
    for (int i = 0; i < count; i++)
    {
        myfile << std::setw(5) << step << std::setw(5) << start + i;
        for (int j = 0; j < count; j++)
        {
            myfile << std::setw(9) << std::setprecision(4)
                   << data[i * count + j];
        }
        myfile << std::endl;
    }
    myfile.close();
}

int main(int argc, char *argv[])
{
    int rank = 0, nproc = 1;
    int retval = 0;

    std::ofstream out("TestSkeletonReaderOutput.txt");
    auto coutbuf = std::cout.rdbuf(out.rdbuf()); // save and redirect

#ifdef ADIOS2_HAVE_MPI
    int wrank = 0, wnproc = 1;
    MPI_Comm mpiReaderComm;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &wnproc);

    const unsigned int color = 2;
    MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &mpiReaderComm);

    MPI_Comm_rank(mpiReaderComm, &rank);
    MPI_Comm_size(mpiReaderComm, &nproc);
#endif

    try
    {

/** ADIOS class factory of IO class objects, Debug is ON by default */
#ifdef ADIOS2_HAVE_MPI
        adios2::ADIOS adios(mpiReaderComm);
#else
        adios2::ADIOS adios;
#endif
        adios2::IO io = adios.DeclareIO("reader");
        io.SetEngine("Skeleton");
        io.SetParameter("VerBose", "5");
        adios2::Engine reader = io.Open(streamname, adios2::Mode::Read);

        while (true)
        {
            adios2::StepStatus status =
                reader.BeginStep(adios2::StepMode::NextAvailable, 60.0f);
            if (status != adios2::StepStatus::OK)
            {
                break;
            }

            // discover in the metadata that the variable exists
            adios2::Variable<float> vMyArray;
            vMyArray = io.InquireVariable<float>("myArray");
            if (!vMyArray)
            {
                std::cout
                    << "Missing 'myArray' variable. The Skeleton reader "
                       "engine must retrieve variables from the writer and "
                       "create Variable objects before they can be "
                       "inquired\n";
            }
            else
            {
                // now read the variable
                // Get the read decomposition
                size_t gndx = vMyArray.Shape()[0];
                size_t ndx = gndx / (size_t)nproc;
                size_t offsx = ndx * (size_t)rank;
                if (rank == nproc - 1)
                {
                    // right-most processes need to read all the rest
                    ndx = gndx - ndx * (size_t)(nproc - 1);
                }
                int step = reader.CurrentStep();
                adios2::Dims count, start;
                count.push_back(ndx);
                start.push_back(offsx);

                vMyArray.SetSelection({start, count});

                std::vector<float> myArray(ndx);
                reader.Get(vMyArray, myArray.data());
                reader.PerformGets();
                printDataStep(myArray.data(), offsx, ndx, rank, step);
            }

            reader.EndStep();
        }
        reader.Close();
    }
    catch (std::invalid_argument &e)
    {
        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
                  << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 1;
    }
    catch (std::ios_base::failure &e)
    {
        std::cout << "IO System base failure exception, STOPPING PROGRAM "
                     "from rank "
                  << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 2;
    }
    catch (std::exception &e)
    {
        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 3;
    }

#ifdef ADIOS2_HAVE_MPI
    MPI_Finalize();
#endif

    std::cout.rdbuf(coutbuf); // reset to standard output again

    return retval;
}
<commit_msg>fix appveyor complaint<commit_after>#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <ios>       //std::ios_base::failure
#include <iostream>  //std::cout
#include <stdexcept> //std::invalid_argument std::exception
#include <vector>

#include <adios2.h>

const std::string streamname = "skeleton_stream";

static void printDataStep(const float *data, const size_t start,
                          const size_t count, const int rank, const size_t step)
{
    std::ofstream myfile;
    std::string filename = "data." + std::to_string(rank);
    if (step == 0)
    {
        myfile.open(filename);
    }
    else
    {
        myfile.open(filename, std::ios::app);
    }

    myfile << "rank=" << rank << " size=" << count << " offsets=" << start
           << " step=" << step << std::endl;

    myfile << " step   row   columns " << start << "..." << start + count - 1
           << std::endl;
    myfile << "        ";
    for (int j = 0; j < count; j++)
    {
        myfile << std::setw(9) << start + j;
    }
    myfile << std::endl;
    myfile << "------------------------------------------------------------"
              "--\n";
    for (int i = 0; i < count; i++)
    {
        myfile << std::setw(5) << step << std::setw(5) << start + i;
        for (int j = 0; j < count; j++)
        {
            myfile << std::setw(9) << std::setprecision(4)
                   << data[i * count + j];
        }
        myfile << std::endl;
    }
    myfile.close();
}

int main(int argc, char *argv[])
{
    int rank = 0, nproc = 1;
    int retval = 0;

    std::ofstream out("TestSkeletonReaderOutput.txt");
    auto coutbuf = std::cout.rdbuf(out.rdbuf()); // save and redirect

#ifdef ADIOS2_HAVE_MPI
    int wrank = 0, wnproc = 1;
    MPI_Comm mpiReaderComm;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
    MPI_Comm_size(MPI_COMM_WORLD, &wnproc);

    const unsigned int color = 2;
    MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &mpiReaderComm);

    MPI_Comm_rank(mpiReaderComm, &rank);
    MPI_Comm_size(mpiReaderComm, &nproc);
#endif

    try
    {

/** ADIOS class factory of IO class objects, Debug is ON by default */
#ifdef ADIOS2_HAVE_MPI
        adios2::ADIOS adios(mpiReaderComm);
#else
        adios2::ADIOS adios;
#endif
        adios2::IO io = adios.DeclareIO("reader");
        io.SetEngine("Skeleton");
        io.SetParameter("VerBose", "5");
        adios2::Engine reader = io.Open(streamname, adios2::Mode::Read);

        while (true)
        {
            adios2::StepStatus status =
                reader.BeginStep(adios2::StepMode::NextAvailable, 60.0f);
            if (status != adios2::StepStatus::OK)
            {
                break;
            }

            // discover in the metadata that the variable exists
            adios2::Variable<float> vMyArray;
            vMyArray = io.InquireVariable<float>("myArray");
            if (!vMyArray)
            {
                std::cout
                    << "Missing 'myArray' variable. The Skeleton reader "
                       "engine must retrieve variables from the writer and "
                       "create Variable objects before they can be "
                       "inquired\n";
            }
            else
            {
                // now read the variable
                // Get the read decomposition
                size_t gndx = vMyArray.Shape()[0];
                size_t ndx = gndx / (size_t)nproc;
                size_t offsx = ndx * (size_t)rank;
                if (rank == nproc - 1)
                {
                    // right-most processes need to read all the rest
                    ndx = gndx - ndx * (size_t)(nproc - 1);
                }
                size_t step = reader.CurrentStep();
                adios2::Dims count, start;
                count.push_back(ndx);
                start.push_back(offsx);

                vMyArray.SetSelection({start, count});

                std::vector<float> myArray(ndx);
                reader.Get(vMyArray, myArray.data());
                reader.PerformGets();
                printDataStep(myArray.data(), offsx, ndx, rank, step);
            }

            reader.EndStep();
        }
        reader.Close();
    }
    catch (std::invalid_argument &e)
    {
        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
                  << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 1;
    }
    catch (std::ios_base::failure &e)
    {
        std::cout << "IO System base failure exception, STOPPING PROGRAM "
                     "from rank "
                  << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 2;
    }
    catch (std::exception &e)
    {
        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
        std::cout << e.what() << "\n";
        retval = 3;
    }

#ifdef ADIOS2_HAVE_MPI
    MPI_Finalize();
#endif

    std::cout.rdbuf(coutbuf); // reset to standard output again

    return retval;
}
<|endoftext|>


<commit_before>/*
 * main.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * @file  main.cpp
 * @brief Command-line version of primesieve, multi-threaded (OpenMP),
 *        compiles on many platforms.
 *
 * primesieve is a highly optimized implementation of the sieve of
 * Eratosthenes that finds prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../expr/ExpressionParser.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../soe/pmath.h"
#include "../soe/cpuid.h"

/// declared in test.cpp
void test();

#include <stdint.h>
#include <exception>
#include <iostream>
#include <iomanip>    /* std::setw(int) */
#include <cstdlib>    /* std::exit(int) */
#include <string>
#include <cstring>    /* std::strlen(const char*) */
#include <cctype>     /* std::tolower(int) */
#include <sstream>

namespace {
  // Unfortunately there is no easy way to get the CPU L1 and L2 cache
  // size, these values are close for most x86-64 CPUs in 2011
  const uint32_t L1_CACHE_SIZE = 64;
  const uint32_t L2_CACHE_SIZE = 512;
  const uint64_t L2_THRESHOLD = ipow(10, 11) * 5;

  bool quietMode = false;
  bool showExpressionResults = false;

  uint64_t start = 0;         /* lower bound for sieving */
  uint64_t stop = 0;          /* upper bound for sieving */
  uint32_t sieveSize = 0;     /* sieve size in KiloBytes */
  uint32_t flags = 0;         /* settings */

  int maxThreads = ParallelPrimeSieve::getMaxThreads();
  int threads = -1;

  std::string primes[7] = { "Prime numbers", "Twin primes", "Prime triplets",
    "Prime quadruplets", "Prime quintuplets", "Prime sextuplets",
    "Prime septuplets" };
}

void version() {
  std::cout << "primesieve 2.0, <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) 2011 Kim Walisch" << std::endl
            << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>." << std::endl
            << "This is free software: you are free to change and redistribute it." << std::endl
            << "There is NO WARRANTY, to the extent permitted by law." << std::endl;
  std::exit(EXIT_SUCCESS);
}

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..." << std::endl
            << "Use the sieve of Eratosthenes to find the prime numbers and prime" << std::endl
            << "k-tuplets between START and STOP < 2^64" << std::endl
            << std::endl
            << "Examples:" << std::endl
            << "  primesieve 1 10000000 -p1" << std::endl
            << "  primesieve 1 1e11 -s 32" << std::endl
            << "  primesieve 1e18 1e18+2**32 -c1234567" << std::endl
            << std::endl
            << "Options:" << std::endl
            << "  -c[N]        Count prime numbers and/or prime k-tuplets," << std::endl
            << "               e.g -c1 count prime numbers, -c3 count prime triplets, ..." << std::endl
            << "               N >= 1 and N <= 7" << std::endl
            << "  -p[N]        Print prime numbers or prime k-tuplets," << std::endl
            << "               e.g -p1 print prime numbers, -p2 print twin primes, ..." << std::endl
            << "               N >= 1 and N <= 7" << std::endl
            << "  -q           Quiet mode, print less output" << std::endl
            << "  -s <SIZE>    Set the sieve size in KiloBytes, e.g. -s 256," << std::endl
            << "               set SIZE to your CPU's L1/L2 cache size for best performance" << std::endl
            << "               SIZE >= 1 and SIZE <= 8192" << std::endl
            << "  -t <THREADS> Set the number of threads for sieving, e.g. -t 4," << std::endl
            << "               THREADS >= 1 and THREADS <= " << maxThreads << " (CPU max threads)" << std::endl
            << "  -test        Run various sieving tests and exit" << std::endl
            << "  -v           Print version and license information and exit" << std::endl;
  std::exit(EXIT_SUCCESS);
}

void exprError(const std::string &str) {
  std::cerr << "Error: \"" << str
            << "\" is not a valid arithmetic expression" << std::endl
            << "Try `primesieve -help' for more information." << std::endl;
  std::exit(EXIT_FAILURE);
}

bool isDigits(const std::string &str) {
  if (str.length() == 0)
    return false;
  return str.find_first_not_of("0123456789") == std::string::npos;
}

/**
 * Process the command-line options.
 * @see help(void)
 */
void processOptions(int argc, char* argv[]) {
  if (argc < 2 || argc > 20)
    help();
  ExpressionParser<uint64_t> parser;
  int i = 1;

  // process the START and STOP numbers
  if (argc > 2) {
    if (!isDigits(argv[i]))
      showExpressionResults = true;
    if (!parser.eval(argv[i]))
      exprError(argv[i]);
    start = parser.getResult();
    i++;
    if (!isDigits(argv[i]))
      showExpressionResults = true;
    if (!parser.eval(argv[i]))
      exprError(argv[i]);
    stop = parser.getResult();
    i++;
  }

  // process the options ([OPTION]...)
  for (; i < argc; i++) {
    char* c = argv[i];
    if (*c != '-' && *c != '/')
      help();
    switch (std::tolower(*(++c)++)) {
      case 'c': do {
                  if (*c < '1' || *c > '7')
                    help();
                  flags |= COUNT_PRIMES << (*c - '1');
                } while (*(++c) != 0);
                break;
      case 'p': if (*c < '1' || *c > '7')
                  help();
                flags |= PRINT_PRIMES << (*c - '1');
                quietMode = true;
                break;
      case 'q': quietMode = true;
                break;
      case 's': if (++i >= argc || !parser.eval(argv[i]))
                  help();
                sieveSize = static_cast<uint32_t> (parser.getResult());
                sieveSize = nextHighestPowerOf2(sieveSize);
                break;
      case 't': if (std::string("test").compare(++argv[i]) == 0) {
                  test();
                  std::exit(EXIT_SUCCESS);
                }
                if (++i >= argc || !parser.eval(argv[i]))
                  help();
                threads = static_cast<int> (parser.getResult());
                break;
      case 'v': version();
      default : help();
    }
  }
}

/**
 * Process the command-line options and start sieving.
 */
int main(int argc, char* argv[]) {
  processOptions(argc, argv);
  int width = static_cast<int> (std::strlen("Sieve size"));
  std::cout.setf(std::ios::left);

  // display expression results
  if (!quietMode && showExpressionResults)
    std::cout << std::setw(width) << "START" << " = " << start << std::endl
              << std::setw(width) << "STOP"  << " = " << stop  << std::endl;

  // set default settings
  if ((flags & COUNT_FLAGS) == 0 && (flags & PRINT_FLAGS) == 0)
    flags |= COUNT_PRIMES;
  if (!quietMode && (flags & PRINT_FLAGS) == 0)
    flags |= PRINT_STATUS;
  if (sieveSize == 0)
    sieveSize = (stop < L2_THRESHOLD) ?L1_CACHE_SIZE :L2_CACHE_SIZE;

  if (!quietMode)
    std::cout << std::setw(width) << "Sieve size" << " = " << sieveSize
              << " KiloBytes" << std::endl;
  try {
    ParallelPrimeSieve primeSieve;
    primeSieve.setStartNumber(start);
    primeSieve.setStopNumber(stop);
    primeSieve.setSieveSize(sieveSize);
    primeSieve.setFlags(flags);

    if (threads == -1)
      threads = primeSieve.getIdealThreadCount();
    if (!quietMode)
      std::cout << std::setw(width) << "Threads" << " = " << threads << std::endl;

    // start sieving primes
    primeSieve.sieve(threads);
    if ((flags & PRINT_STATUS) || (flags & PRINT_FLAGS))
      std::cout << std::endl;

    // get max output string length
    width = static_cast<int> (std::strlen("Time elapsed"));
    for (int i = 0; i < primeSieve.COUNTS_SIZE; i++) {
      if (flags & (COUNT_PRIMES << i)) {
        int length = static_cast<int> (primes[i].length());
        if (width < length)
          width = length;
      }
    }
    // print prime count results
    for (int i = 0; i < primeSieve.COUNTS_SIZE; i++) {
      if (flags & (COUNT_PRIMES << i))
        std::cout << std::setw(width) << primes[i] << " : " <<
            primeSieve.getCounts(i) << std::endl;
    }
    std::cout << std::setw(width) << "Time elapsed" << " : " <<
        primeSieve.getTimeElapsed() << " sec" << std::endl;
  }
  catch (std::exception& ex) {
    std::cerr << "Error: " << ex.what() << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    std::exit(EXIT_FAILURE);
  }
  return 0;
}
<commit_msg>cosmetics<commit_after>/*
 * main.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2011 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * @file  main.cpp
 * @brief Command-line version of primesieve, multi-threaded (OpenMP),
 *        compiles on many platforms.
 *
 * primesieve is a highly optimized implementation of the sieve of
 * Eratosthenes that finds prime numbers and prime k-tuplets (twin
 * primes, prime triplets, ...) up to 2^64 maximum.
 */

#include "../expr/ExpressionParser.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../soe/pmath.h"
#include "../soe/cpuid.h"

/// declared in test.cpp
void test();

#include <stdint.h>
#include <exception>
#include <iostream>
#include <iomanip>    /* std::setw(int) */
#include <cstdlib>    /* std::exit(int) */
#include <string>
#include <cstring>    /* std::strlen(const char*) */
#include <cctype>     /* std::tolower(int) */
#include <sstream>

namespace {
  // Unfortunately there is no easy way to get the CPU L1 and L2 cache
  // size, these values are close for most x86-64 CPUs in 2011
  const uint32_t L1_CACHE_SIZE = 64;
  const uint32_t L2_CACHE_SIZE = 512;
  const uint64_t L2_THRESHOLD = ipow(10, 11) * 5;

  bool quietMode = false;
  bool showExpressionResults = false;

  uint64_t numbers[2] = {0, 0};  /* start and stop number for sieving */
  uint32_t sieveSize = 0;        /* sieve size in KiloBytes */
  uint32_t flags = 0;            /* settings */

  int maxThreads = ParallelPrimeSieve::getMaxThreads();
  int threads = -1;

  std::string primes[7] = { "Prime numbers", "Twin primes", "Prime triplets",
    "Prime quadruplets", "Prime quintuplets", "Prime sextuplets",
    "Prime septuplets" };
}

void version() {
  std::cout << "primesieve 2.0, <http://primesieve.googlecode.com>" << std::endl
            << "Copyright (C) 2011 Kim Walisch" << std::endl
            << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>." << std::endl
            << "This is free software: you are free to change and redistribute it." << std::endl
            << "There is NO WARRANTY, to the extent permitted by law." << std::endl;
  std::exit(EXIT_SUCCESS);
}

void help() {
  std::cout << "Usage: primesieve START STOP [OPTION]..." << std::endl
            << "Use the sieve of Eratosthenes to find the prime numbers and prime" << std::endl
            << "k-tuplets between START and STOP < 2^64" << std::endl
            << std::endl
            << "Examples:" << std::endl
            << "  primesieve 1 10000000 -p1" << std::endl
            << "  primesieve 1 1e11 -s 32" << std::endl
            << "  primesieve 1e18 1e18+2**32 -c1234567" << std::endl
            << std::endl
            << "Options:" << std::endl
            << "  -c[N]        Count prime numbers and/or prime k-tuplets," << std::endl
            << "               e.g -c1 count prime numbers, -c3 count prime triplets, ..." << std::endl
            << "               N >= 1 and N <= 7" << std::endl
            << "  -p[N]        Print prime numbers or prime k-tuplets," << std::endl
            << "               e.g -p1 print prime numbers, -p2 print twin primes, ..." << std::endl
            << "               N >= 1 and N <= 7" << std::endl
            << "  -q           Quiet mode, print less output" << std::endl
            << "  -s <SIZE>    Set the sieve size in KiloBytes, e.g. -s 256," << std::endl
            << "               set SIZE to your CPU's L1/L2 cache size for best performance" << std::endl
            << "               SIZE >= 1 and SIZE <= 8192" << std::endl
            << "  -t <THREADS> Set the number of threads for sieving, e.g. -t 4," << std::endl
            << "               THREADS >= 1 and THREADS <= " << maxThreads << " (CPU max threads)" << std::endl
            << "  -test        Run various sieving tests and exit" << std::endl
            << "  -v           Print version and license information and exit" << std::endl;
  std::exit(EXIT_SUCCESS);
}

bool isDigits(const std::string &str) {
  if (str.length() == 0)
    return false;
  return str.find_first_not_of("0123456789") == std::string::npos;
}

/**
 * Process the command-line options.
 * @see help(void)
 */
void processOptions(int argc, char* argv[]) {
  if (argc < 2 || argc > 20)
    help();
  ExpressionParser<uint64_t> parser;
  int i = 1;

  // process the START and STOP numbers
  if (argc > 2)
    for (; i <= 2; i++) {
      if (!parser.eval(argv[i])) {
        std::cerr << "Error: \"" << argv[i]  << "\" is not a valid arithmetic expression" << std::endl
                  << "Try `primesieve -help' for more information." << std::endl;
        std::exit(EXIT_FAILURE);
      }
      numbers[i-1] = parser.getResult();
      if (!isDigits(argv[i]))
        showExpressionResults = true;
    }

  // process the options ([OPTION]...)
  for (; i < argc; i++) {
    char* c = argv[i];
    if (*c != '-' && *c != '/')
      help();
    switch (std::tolower(*(++c)++)) {
      case 'c': do {
                  if (*c < '1' || *c > '7')
                    help();
                  flags |= COUNT_PRIMES << (*c - '1');
                } while (*(++c) != 0);
                break;
      case 'p': if (*c < '1' || *c > '7')
                  help();
                flags |= PRINT_PRIMES << (*c - '1');
                quietMode = true;
                break;
      case 'q': quietMode = true;
                break;
      case 's': if (++i >= argc || !parser.eval(argv[i]))
                  help();
                sieveSize = static_cast<uint32_t> (parser.getResult());
                sieveSize = nextHighestPowerOf2(sieveSize);
                break;
      case 't': if (std::string("test").compare(++argv[i]) == 0) {
                  test();
                  std::exit(EXIT_SUCCESS);
                }
                if (++i >= argc || !parser.eval(argv[i]))
                  help();
                threads = static_cast<int> (parser.getResult());
                break;
      case 'v': version();
      default : help();
    }
  }
}

/**
 * Process the command-line options and start sieving.
 */
int main(int argc, char* argv[]) {
  processOptions(argc, argv);
  int width = static_cast<int> (std::strlen("Sieve size"));
  std::cout.setf(std::ios::left);

  // display expression results
  if (!quietMode && showExpressionResults)
    std::cout << std::setw(width) << "START" << " = " << numbers[0] << std::endl
              << std::setw(width) << "STOP"  << " = " << numbers[1]  << std::endl;

  // set default settings
  if ((flags & COUNT_FLAGS) == 0 && (flags & PRINT_FLAGS) == 0)
    flags |= COUNT_PRIMES;
  if (!quietMode && (flags & PRINT_FLAGS) == 0)
    flags |= PRINT_STATUS;
  if (sieveSize == 0)
    sieveSize = (numbers[1] < L2_THRESHOLD) ?L1_CACHE_SIZE :L2_CACHE_SIZE;

  if (!quietMode)
    std::cout << std::setw(width) << "Sieve size" << " = " << sieveSize
              << " KiloBytes" << std::endl;
  try {
    ParallelPrimeSieve primeSieve;
    primeSieve.setStartNumber(numbers[0]);
    primeSieve.setStopNumber(numbers[1]);
    primeSieve.setSieveSize(sieveSize);
    primeSieve.setFlags(flags);

    if (threads == -1)
      threads = primeSieve.getIdealThreadCount();
    if (!quietMode)
      std::cout << std::setw(width) << "Threads" << " = " << threads << std::endl;

    // start sieving primes
    primeSieve.sieve(threads);
    if ((flags & PRINT_STATUS) || (flags & PRINT_FLAGS))
      std::cout << std::endl;

    // get max output string length
    width = static_cast<int> (std::strlen("Time elapsed"));
    for (int i = 0; i < primeSieve.COUNTS_SIZE; i++) {
      if (flags & (COUNT_PRIMES << i)) {
        int length = static_cast<int> (primes[i].length());
        if (width < length)
          width = length;
      }
    }
    // print prime count results
    for (int i = 0; i < primeSieve.COUNTS_SIZE; i++) {
      if (flags & (COUNT_PRIMES << i))
        std::cout << std::setw(width) << primes[i] << " : " <<
            primeSieve.getCounts(i) << std::endl;
    }
    std::cout << std::setw(width) << "Time elapsed" << " : " <<
        primeSieve.getTimeElapsed() << " sec" << std::endl;
  }
  catch (std::exception& ex) {
    std::cerr << "Error: " << ex.what() << std::endl
              << "Try `primesieve -help' for more information." << std::endl;
    std::exit(EXIT_FAILURE);
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to
    deal in the Software without restriction, including without limitation the
    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    sell copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <cassert>
#include <cstring>
#include <algorithm>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
#endif
#if (defined(__clang__))
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1600))
    #define ZMQ_HAS_RVALUE_REFS
#endif

// In order to prevent unused variable warnings when building in non-debug
// mode use this macro to make assertions.
#ifndef NDEBUG
#   define ZMQ_ASSERT(expression) assert(expression)
#else
#   define ZMQ_ASSERT(expression) (expression)
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline message_t (message_t &&rhs) : msg (rhs.msg)
        {
            int rc = zmq_msg_init (&rhs.msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t &operator = (message_t &&rhs)
        {
            std::swap (msg, rhs.msg);
            return *this;
        }
#endif

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            ZMQ_ASSERT (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline const void* data () const
        {
            return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
        }

        inline size_t size () const
        {
            return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            close();
        }

        inline void close()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = NULL;
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline bool connected()
        {
            return(ptr != NULL);
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_sendmsg (ptr, &(msg_.msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_recvmsg (ptr, &(msg_->msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:

        void *ptr;

        socket_t (const socket_t&);
        void operator = (const socket_t&);
    };

}

#endif

<commit_msg>Don't use deprecated functions<commit_after>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to
    deal in the Software without restriction, including without limitation the
    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    sell copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <algorithm>
#include <cassert>
#include <cstring>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
#endif
#if (defined(__clang__))
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1600))
    #define ZMQ_HAS_RVALUE_REFS
#endif

// In order to prevent unused variable warnings when building in non-debug
// mode use this macro to make assertions.
#ifndef NDEBUG
#   define ZMQ_ASSERT(expression) assert(expression)
#else
#   define ZMQ_ASSERT(expression) (expression)
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline message_t (message_t &&rhs) : msg (rhs.msg)
        {
            int rc = zmq_msg_init (&rhs.msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t &operator = (message_t &&rhs)
        {
            std::swap (msg, rhs.msg);
            return *this;
        }
#endif

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            ZMQ_ASSERT (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline const void* data () const
        {
            return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
        }

        inline size_t size () const
        {
            return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            close();
        }

        inline void close()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = NULL;
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline bool connected()
        {
            return(ptr != NULL);
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:

        void *ptr;

        socket_t (const socket_t&);
        void operator = (const socket_t&);
    };

}

#endif

<|endoftext|>


<commit_before>#include <cassert>
#include <fstream>
#include <iostream>
#include <strstream>

#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif

//These came from the debug test.
#include <cstdio>
#include <ctime>
#include <string>
#include <vector>

#include <util/PlatformUtils.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanFileOutputStream.hpp>
#include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
#include <XercesParserLiaison/XercesDOMSupport.hpp>

#include <XPath/XObjectFactoryDefault.hpp>
#include <XPath/XPathSupportDefault.hpp>
#include <XPath/XPathFactoryDefault.hpp>

#include <XSLT/StylesheetConstructionContextDefault.hpp>
#include <XSLT/StylesheetExecutionContextDefault.hpp>
#include <XSLT/StylesheetRoot.hpp>
#include <XSLT/XSLTEngineImpl.hpp>
#include <XSLT/XSLTInit.hpp>
#include <XSLT/XSLTInputSource.hpp>
#include <XSLT/XSLTProcessorEnvSupportDefault.hpp>
#include <XSLT/XSLTResultTarget.hpp>

#include <XercesParserLiaison/XercesParserLiaison.hpp>

//This is here for the threads.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winbase.h>
#define THREADFUNCTIONRETURN DWORD WINAPI

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::cin;
	using std::endl;
	using std::ifstream;
	using std::ios_base;
	using std::ostrstream;
	using std::string;
#endif

// This is here for memory leak testing.
#if defined(_DEBUG)
#include <crtdbg.h>
#endif

const char* const	xslStylesheets[] =
{
	"v:\\xsl-test\\prod\\misc\\misc-chess",
	"v:\\xsl-test\\perf\\basic\\basic-all_well",
	"v:\\xsl-test\\perf\\basic\\basic-datetranscode",
	"v:\\xsl-test\\perf\\basic\\basic-dict2",
	"v:\\xsl-test\\perf\\basic\\basic-Fischer-Euwe",
	"v:\\xsl-test\\perf\\basic\\basic-queens",
	"v:\\xsl-test\\perf\\large\\large-all_well",
	//"v:\\xsl-test\\perf\\large\\large-evans_large",
	"v:\\xsl-test\\perf\\nodes\\nodes-fancy_xml_tree_viewer_34",
	"v:\\xsl-test\\perf\\nodes\\nodes-showtree-19991008",
	"v:\\xsl-test\\perf\\sort\\sort-big",
	"v:\\xsl-test\\perf\\xpath\\xpath-evans_small",
	"v:\\xsl-test\\perf\\xpath\\xpath-evans_tiny",
	0
};

// Used to hold compiled stylesheet, and source document.
StylesheetRoot*		glbStylesheetRoot[sizeof(xslStylesheets) / sizeof(const char*)];

XalanNode*			glbSourceDoc[sizeof(xslStylesheets) / sizeof(const char*)];

void
outputMessage(int iter)
{
		cout << "\n" << "Starting Iteration: " << iter << '\0';
}

int
main(
			int				argc,
			const char*		argv [])
{
	assert(sizeof(glbStylesheetRoot) == sizeof(glbSourceDoc));

#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	if (argc > 2)
	{
		cerr << "Usage: perf"
			 << endl
			 << endl;
	}
	else
	{
		int	iterCount = 1;

		if (argc == 2)
		{
			iterCount = atoi(argv[1]);
		}

		try
		{
			// Call the static initializers...
			XMLPlatformUtils::Initialize();

			{
				XSLTInit	theInit;

				// Create the necessary stuff to compile the stylesheet.
				XercesDOMSupport			    csDOMSupport;
				XercesParserLiaison				csParserLiaison(csDOMSupport);
				XPathSupportDefault				csXPathSupport(csDOMSupport);
				XSLTProcessorEnvSupportDefault	csXSLTProcessorEnvSupport;
				XObjectFactoryDefault			csXObjectFactory;
				XPathFactoryDefault				csXPathFactory;

				// Create a processor to compile the stylesheet...
				XSLTEngineImpl	csProcessor(
						csParserLiaison,
						csXPathSupport,
						csXSLTProcessorEnvSupport,
						csDOMSupport,
						csXObjectFactory,
						csXPathFactory);

				// Connect the processor to the support object...
				csXSLTProcessorEnvSupport.setProcessor(&csProcessor);

				// Create separate factory support objects so the stylesheet's
				// factory-created XObject and XPath instances are independent
				// from processor's.
				XObjectFactoryDefault	csStylesheetXObjectFactory;
				XPathFactoryDefault		csStylesheetXPathFactory;

				// Create a stylesheet construction context, using the
				// stylesheet's factory support objects.
				StylesheetConstructionContextDefault	csConstructionContext(
														csProcessor,
														csXSLTProcessorEnvSupport,
														csStylesheetXPathFactory);

				const XalanDOMString  theXSLSuffix(".xsl");
				const XalanDOMString  theXMLSuffix(".xml");
				const XalanDOMString  theoutputSuffix(".out");

				for(int i = 0; xslStylesheets[i] != 0; i++)
				{
					const XalanDOMString  theXSLFilename(XalanDOMString(xslStylesheets[i]) + theXSLSuffix);
					const XalanDOMString  theXMLFilename(XalanDOMString(xslStylesheets[i]) + theXMLSuffix);

					cout << "Now compiling Stylesheet: " << xslStylesheets[i] << endl;

					//Generate the XML and XSL input objects.
					XSLTInputSource		csStylesheetSourceXSL(c_wstr(theXSLFilename));
					XSLTInputSource		csDocumentSource(c_wstr(theXMLFilename));

					// Ask the processor to create a StylesheetRoot for the specified
					// input XSL.  This is the compiled stylesheet.  We don't have to
					// delete it, since it is owned by the StylesheetConstructionContext
					// instance.
					glbStylesheetRoot[i] = csProcessor.processStylesheet(csStylesheetSourceXSL,
														   csConstructionContext);
					assert(glbStylesheetRoot[i] != 0);

					// Have the processor create a compiled SourceDocument for the specified
					// input XML.
					glbSourceDoc[i] = csProcessor.getSourceTreeFromInput(csDocumentSource);
					assert(glbSourceDoc[i] != 0);
				}

					for(int ii = 0; xslStylesheets[ii] != 0; ii++)
					{
						cout << endl << "Now running test: " << xslStylesheets[ii] << endl;

						// Create the necessary stuff to run the processor.
						XercesDOMSupport				psDOMSupport;
						XercesParserLiaison				psParserLiaison(psDOMSupport);
						XPathSupportDefault				psXPathSupport(psDOMSupport);
						XSLTProcessorEnvSupportDefault	psXSLTProcessorEnvSupport;
						XObjectFactoryDefault			psXObjectFactory;
						XPathFactoryDefault				psXPathFactory;

						// Create a processor to perform the transform.
						XSLTEngineImpl	psProcessor(
							psParserLiaison,
							psXPathSupport,
							psXSLTProcessorEnvSupport,
							psDOMSupport,
							psXObjectFactory,
							psXPathFactory);

						// Connect the processor to the support object...
						psXSLTProcessorEnvSupport.setProcessor(&psProcessor);

						// The execution context uses the same factory support objects as
						// the processor, since those objects have the same lifetime as
						// other objects created as a result of the execution.
						StylesheetExecutionContextDefault		psExecutionContext(
								psProcessor,
								psXSLTProcessorEnvSupport,
								psXPathSupport,
								psXObjectFactory);

						const XalanDOMString  outputFileName(XalanDOMString(xslStylesheets[ii]) + theoutputSuffix);

						//Generate the XML input and output objects.
						XSLTInputSource		csDocumentSource(glbSourceDoc[ii]);
						XSLTResultTarget	theResultTarget(outputFileName);

						// Set the stylesheet to be the compiled stylesheet. Then do the transform.
						const double startTime = clock();
						cout << "Clock before transforms: " << startTime << endl;
						for(int j = 0; j < iterCount; ++j)
						{
							psProcessor.setStylesheetRoot(glbStylesheetRoot[ii]);
							psProcessor.process(csDocumentSource, theResultTarget,psExecutionContext);
							psExecutionContext.reset();
						}
						const double endTime = clock();
						cout << "Clock after transforms: " << endTime << endl;
						cout << "Total clock ticks: " << endTime - startTime << endl;
						const double	millis = ((endTime - startTime) / CLOCKS_PER_SEC) * 1000.0;
						cout << "Milliseconds: " << millis << endl;
						cout << "Averaged: " << millis / iterCount << " per iteration" << endl;
					}

			}

			XMLPlatformUtils::Terminate();
		}
		catch(...)
		{
			cerr << "Exception caught!!!"
				 << endl
				 << endl;
		}
	}

	return 0;
}
<commit_msg>Removed second instance of processor,  and did alot of cleanup.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include <cassert>
#include <fstream>
#include <iostream>
#include <strstream>

#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif

//These came from the debug test.
#include <cstdio>
#include <ctime>
#include <string>
#include <vector>

#include <util/PlatformUtils.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanFileOutputStream.hpp>
#include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
#include <XercesParserLiaison/XercesDOMSupport.hpp>

#include <XPath/XObjectFactoryDefault.hpp>
#include <XPath/XPathSupportDefault.hpp>
#include <XPath/XPathFactoryDefault.hpp>

#include <XSLT/StylesheetConstructionContextDefault.hpp>
#include <XSLT/StylesheetExecutionContextDefault.hpp>
#include <XSLT/StylesheetRoot.hpp>
#include <XSLT/XSLTEngineImpl.hpp>
#include <XSLT/XSLTInit.hpp>
#include <XSLT/XSLTInputSource.hpp>
#include <XSLT/XSLTProcessorEnvSupportDefault.hpp>
#include <XSLT/XSLTResultTarget.hpp>

#include <XercesParserLiaison/XercesParserLiaison.hpp>

//This is here for the threads.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winbase.h>
#define THREADFUNCTIONRETURN DWORD WINAPI

#if !defined(XALAN_NO_NAMESPACES)
	using std::cerr;
	using std::cout;
	using std::cin;
	using std::endl;
	using std::ifstream;
	using std::ios_base;
	using std::ostrstream;
	using std::string;
#endif

// This is here for memory leak testing.
#if defined(_DEBUG)
#include <crtdbg.h>
#endif

const char* const	xslStylesheets[] =
{
	"v:\\xsl-test\\perf\\basic\\basic-all_well",
	"v:\\xsl-test\\perf\\basic\\basic-datetranscode",
	"v:\\xsl-test\\perf\\basic\\basic-dict2",
	"v:\\xsl-test\\perf\\basic\\basic-Fischer-Euwe",
	"v:\\xsl-test\\perf\\basic\\basic-queens",
	"v:\\xsl-test\\perf\\large\\large-all_well",
	//"v:\\xsl-test\\perf\\large\\large-evans_large",
	"v:\\xsl-test\\perf\\nodes\\nodes-fancy_xml_tree_viewer_34",
	"v:\\xsl-test\\perf\\nodes\\nodes-showtree-19991008",
	"v:\\xsl-test\\perf\\sort\\sort-big",
	"v:\\xsl-test\\perf\\xpath\\xpath-evans_small",
	"v:\\xsl-test\\perf\\xpath\\xpath-evans_tiny",
	0
};

// Used to hold compiled stylesheet, and source document.
XalanNode*		glbSourceXML[sizeof(xslStylesheets) / sizeof(const char*)];
StylesheetRoot*	glbStylesheetRoot[sizeof(xslStylesheets) / sizeof(const char*)];

void outputMessage(int iter)
{
	cout << "\n" << "Starting Iteration: " << iter << '\0';
}

int main( int argc,	const char* argv [])
{
	assert(sizeof(glbStylesheetRoot) == sizeof(glbSourceXML));

#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

	if (argc > 2)
	{
		cerr << "Usage: perf" << endl  << endl;
	}
	else
	{
		int	iterCount = 1;
		if (argc == 2)
		{
			iterCount = atoi(argv[1]);
		}

		try
		{
			// Call the static initializers...
			XMLPlatformUtils::Initialize();

			{
				XSLTInit	theInit;

				const XalanDOMString  XSLSuffix(".xsl");
				const XalanDOMString  XMLSuffix(".xml");
				const XalanDOMString  outputSuffix(".out");

				// Create the necessary support objects to instantiate a processor.
				XercesDOMSupport			    csDOMSupport;
				XercesParserLiaison				csParserLiaison(csDOMSupport);
				XPathSupportDefault				csXPathSupport(csDOMSupport);
				XSLTProcessorEnvSupportDefault	csXSLTProcessorEnvSupport;
				XObjectFactoryDefault			csXObjectFactory;
				XPathFactoryDefault				csXPathFactory;

				// Create a processor for stylesheet compilation and connect to
				// ProcessorEnvSupport object
				XSLTEngineImpl	csProcessor(
						csParserLiaison,
						csXPathSupport,
						csXSLTProcessorEnvSupport,
						csDOMSupport,
						csXObjectFactory,
						csXPathFactory);
				csXSLTProcessorEnvSupport.setProcessor(&csProcessor);

				// Create separate factory support object, so the stylesheet's
				// factory-created XPath instance are independent from processor's.
				XPathFactoryDefault			ssXPathFactory;

				// Create a stylesheet construction context, using the
				// stylesheet's factory support objects.
				StylesheetConstructionContextDefault	csConstructionContext(
														csProcessor,
														csXSLTProcessorEnvSupport,
														ssXPathFactory);

				for(int i = 0; xslStylesheets[i] != 0; i++)
				{
					const XalanDOMString  theXSLfile(XalanDOMString(xslStylesheets[i]) + XSLSuffix);
					const XalanDOMString  theXMLfile(XalanDOMString(xslStylesheets[i]) + XMLSuffix);

					cout << "Now compiling Stylesheet: " << xslStylesheets[i] << endl;

					//Generate the XML and XSL input objects.
					XSLTInputSource		csStylesheetSourceXSL(c_wstr(theXSLfile));
					XSLTInputSource		csSourceXML(c_wstr(theXMLfile));

					// Ask the processor to create a compiled stylesheet (StylesheetRoot) for the
					// specified input XSL. We don't have to delete it, since it is owned by the
					// StylesheetConstructionContext instance.
					glbStylesheetRoot[i] = csProcessor.processStylesheet(csStylesheetSourceXSL,
														   csConstructionContext);
					assert(glbStylesheetRoot[i] != 0);

					// Have the processor create a compiled SourceDocument for the specified
					// input XML.
					glbSourceXML[i] = csProcessor.getSourceTreeFromInput(csSourceXML);
					assert(glbSourceXML[i] != 0);
				}

				for(int ii = 0; xslStylesheets[ii] != 0; ii++)
				{
					cout << endl << "Now running test: " << xslStylesheets[ii] << endl;

					// The execution context uses the same factory support objects as
					// the processor, since those objects have the same lifetime as
					// other objects created as a result of the execution.
					StylesheetExecutionContextDefault	psExecutionContext(
							csProcessor,
							csXSLTProcessorEnvSupport,
							csXPathSupport,
							csXObjectFactory);

					const XalanDOMString  outputfile(XalanDOMString(xslStylesheets[ii]) + outputSuffix);

					//Generate the XML input and output objects.
					XSLTInputSource		csSourceXML(glbSourceXML[ii]);
					XSLTResultTarget	theResultTarget(outputfile);

					// Set the stylesheet to be the compiled stylesheet. Then do the transform.
					const double startTime = clock();
					cout << "Clock before transforms: " << startTime << endl;
					for(int j = 0; j < iterCount; ++j)
					{
						csProcessor.setStylesheetRoot(glbStylesheetRoot[ii]);
						csProcessor.process(csSourceXML, theResultTarget,psExecutionContext);
						psExecutionContext.reset();
					}
					const double endTime = clock();
					cout << "Clock after transforms: " << endTime << endl;
					cout << "Total clock ticks: " << endTime - startTime << endl;
					const double	millis = ((endTime - startTime) / CLOCKS_PER_SEC) * 1000.0;
					cout << "Milliseconds: " << millis << endl;
					cout << "Averaged: " << millis / iterCount << " per iteration" << endl;
				}

			}

			XMLPlatformUtils::Terminate();
		}
		catch(...)
		{
			cerr << "Exception caught!!!"
				 << endl
				 << endl;
		}
	}

	return 0;
}
<|endoftext|>