#!/usr/bin/perl
#



print <<EOF
/* This file is autogenerated.  Do not edit. */
/*
 * LIBOIL - Library of Optimized Inner Loops
 * Copyright (c) 2005 David A. Schleef <ds\@schleef.org>
 * 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.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <math.h>

#include <liboil/liboil.h>
#include <liboil/liboilclasses.h>

EOF
;


sub clamp_pointer
{
	my $kernel = shift;
	my $type = shift;
	my $low = 1;
	my $high = 1;

	($kernel eq "clamphigh") and $low = 0;
	($kernel eq "clamplow") and $high = 0;

	print <<EOF
static void
${kernel}_${type}_pointer (oil_type_${type} *dest, oil_type_${type} *src1,
    int n
EOF
;

	$low && print ("    , oil_type_${type} *low\n");
	$high && print ("    , oil_type_${type} *high\n");

	print <<EOF
    )
{
  while (n) {
    oil_type_${type} x = *src1;
EOF
;
	($low) and print ("    if (x < *low) x = *low;\n");
	($high) and print ("    if (x > *high) x = *high;\n");

	print <<EOF
    *dest = x;
    dest++;
    src1++;
    n--;
  }
}
OIL_DEFINE_IMPL (${kernel}_${type}_pointer, ${kernel}_${type});

EOF
;
}

sub clamp_unroll4
{
	my $kernel = shift;
	my $type = shift;
	my $low = 1;
	my $high = 1;

	($kernel eq "clamphigh") and $low = 0;
	($kernel eq "clamplow") and $high = 0;

	$proto = "";
	$low and $proto .= ", oil_type_${type} *low";
	$high and $proto .= ", oil_type_${type} *high";

	$clamp = "";
	$low and $clamp .= "    if (x < *low) x = *low;\n";
	$high and $clamp .= "    if (x > *high) x = *high;\n";

	print <<EOF
static void
${kernel}_${type}_unroll4 (oil_type_${type} *dest, oil_type_${type} *src,
    int n $proto)
{
  oil_type_${type} x;
  while (n&3) {
    x = *src;
$clamp
    *dest = x;
    dest++;
    src++;
    n--;
  }
  n >>= 2;
  while (n) {
    x = src[0];
$clamp
    dest[0] = x;
    x = src[1];
$clamp
    dest[1] = x;
    x = src[2];
$clamp
    dest[2] = x;
    x = src[3];
$clamp
    dest[3] = x;
    dest+=4;
    src+=4;
    n--;
  }
}
OIL_DEFINE_IMPL (${kernel}_${type}_unroll4, ${kernel}_${type});

EOF
;
}

sub clamp_trick
{
	my $kernel = shift;
	my $type = shift;
	my $low = 1;
	my $high = 1;

	($kernel eq "clamphigh") and $low = 0;
	($kernel eq "clamplow") and $high = 0;

	$proto = "";
	$low and $proto .= ", oil_type_${type} *low";
	$high and $proto .= ", oil_type_${type} *high";

	$clamp = "";
	$low and $clamp .= "    x = x - (((x-*low)>>31)&(x-*low));\n";
	$high and $clamp .= "    x = x + (((*high-x)>>31)&(*high-x));\n";

	print <<EOF
static void
${kernel}_${type}_trick (oil_type_${type} *dest, oil_type_${type} *src,
    int n $proto)
{
  int x;
  while (n&3) {
    x = *src;
$clamp
    *dest = x;
    dest++;
    src++;
    n--;
  }
  n >>= 2;
  while (n) {
    x = src[0];
$clamp
    dest[0] = x;
    x = src[1];
$clamp
    dest[1] = x;
    x = src[2];
$clamp
    dest[2] = x;
    x = src[3];
$clamp
    dest[3] = x;
    dest+=4;
    src+=4;
    n--;
  }
}
OIL_DEFINE_IMPL (${kernel}_${type}_trick, ${kernel}_${type});

EOF
;
}


clamp_pointer("clamp", "s8");
clamp_pointer("clamp", "u8");
clamp_pointer("clamp", "s16");
clamp_pointer("clamp", "u16");
clamp_pointer("clamp", "s32");
clamp_pointer("clamp", "u32");

clamp_unroll4("clamp", "s8");
clamp_unroll4("clamp", "u8");
clamp_unroll4("clamp", "s16");
clamp_unroll4("clamp", "u16");
clamp_unroll4("clamp", "s32");
clamp_unroll4("clamp", "u32");

clamp_trick("clamp", "s8");
clamp_trick("clamp", "u8");
clamp_trick("clamp", "s16");
clamp_trick("clamp", "u16");

clamp_pointer("clamphigh", "s8");
clamp_pointer("clamphigh", "u8");
clamp_pointer("clamphigh", "s16");
clamp_pointer("clamphigh", "u16");
clamp_pointer("clamphigh", "s32");
clamp_pointer("clamphigh", "u32");

clamp_unroll4("clamphigh", "s8");
clamp_unroll4("clamphigh", "u8");
clamp_unroll4("clamphigh", "s16");
clamp_unroll4("clamphigh", "u16");
clamp_unroll4("clamphigh", "s32");
clamp_unroll4("clamphigh", "u32");

clamp_trick("clamphigh", "s8");
clamp_trick("clamphigh", "u8");
clamp_trick("clamphigh", "s16");
clamp_trick("clamphigh", "u16");

clamp_pointer("clamplow", "s8");
clamp_pointer("clamplow", "u8");
clamp_pointer("clamplow", "s16");
clamp_pointer("clamplow", "u16");
clamp_pointer("clamplow", "s32");
clamp_pointer("clamplow", "u32");

clamp_unroll4("clamplow", "s8");
clamp_unroll4("clamplow", "u8");
clamp_unroll4("clamplow", "s16");
clamp_unroll4("clamplow", "u16");
clamp_unroll4("clamplow", "s32");
clamp_unroll4("clamplow", "u32");

clamp_trick("clamplow", "s8");
clamp_trick("clamplow", "u8");
clamp_trick("clamplow", "s16");
clamp_trick("clamplow", "u16");

exit 0;

