/*
 * Copyright (c) 1994-2005 by Wayne C. Gramlich.
 * All rights reserved.
 */

/*
 * This file implements the float base type operations in ANSI-C.
 */

#ifndef ERROR_EXPORTS_H
#include "error_exports.h"
#endif

#ifndef STHEADERS_H
#include "stheaders.h"
#endif

#ifndef UNIX_ASSERT_H
#include "unix_assert.h"
#endif

#include <math.h>

typedef int Float;

typedef struct float16_struct {
	float floats[16];
} *Float16;

struct float16_struct float____initial = {
	(float)0.0,
};

float float__one = 1.0;

float float__zero = 0.0;

float float___initial = 0.0;

Float16 float16___initial = &float____initial;

extern module___object float__module__object;
extern type___reference float_type_ref;

static object___object float_initial_object = {
	"",				/* Package name */
	"float",			/* Type name */
	"??",				/* Object name */
	(type___reference *)0,		/*XXX: Fix me */
	(int *)0,			/* Size of float object */
	0,				/* Static needs count */
	(need___entry *)0,		/*XXX: Fix me Static needs */
	0,				/* Parameter needs count */
	(need___entry *)0,		/* Parameter needs */
	(void **)&float___initial,	/* Object pointer */
	(instantiation___object *)0	/* Instantiation list */
};
static object___object *object_list[1] = {
	&float_initial_object,
};

void
float__external__initialize(void)
{
	float__module__object.object_count = 1;
	float__module__object.objects = object_list;
}

void
float16__external__initialize(void)
{
	/* Do nothing */
}

Float
float__arc_cosine(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)acos((double)a);
	return *((Float *)&result);
}

Float
float__arc_sine(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)asin((double)a);
	return *((Float *)&result);
}

Float
float__arc_tangent(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)atan((double)a);
	return *((Float *)&result);
}

Float
float__arc_tangent2(
	Float	y,
	Float	x)
{
	float	a;
	float	b;
	float	result;

	a = *((float *)&x);
	b = *((float *)&y);
	result = (float)atan2((double)b, (double)a);
	/* (void)printf("atan2(%f, %f)=>%f\n", a, b, result); */
	return *((Float *)&result);
}

Float
float__add(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = l + r;
	return *((Float *)&result);
}

void
float__buffer_append(
	float	arg,
	Str	buffer)
{
	char chr;
	char *pointer;
	char local_buffer[30];

	(void)sprintf(local_buffer, "%g", (double)arg);
	pointer = local_buffer;
	while ((chr = *pointer++) != '\0') {
		string__character_append(buffer, chr);
	}
}


Float
float__ceiling(
	Float	arg)
{
	float	result;
	float	a;

	result = ceilf(*((float *)&arg));
	return *((Float *)&result);
}

float
float__copy(
	float	arg)
{
	return arg;
}

Float
float__cosine(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)cos((double)a);
	return *((Float *)&result);
}

Float
float__divide(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = l / r;
	/* (void)printf("%f/%f=%f ", l, r, result); */
	return *((Float *)&result);
}

int
float__equal(
	Float	left,
	Float	right)
{
	float	l;
	float	r;

	l = *((float *)&left);
	r = *((float *)&right);
	return l == r;
}

Float
float__floor(
	Float	arg)
{
	float	result;
	float	a;

	result = floorf(*((float *)&arg));
	return *((Float *)&result);
}

int
float__greater_than(
	Float	left,
	Float	right)
{
	float	l;
	float	r;

	l = *((float *)&left);
	r = *((float *)&right);
	return l > r;
}

unsigned
float__hash(
	Float	arg)
{
	float	a;

	a = *((float *)&arg);
	return *((unsigned *)&a);
}

int
float__integer_convert(
	Float	arg)
{
	float	a;
	a = *((float *)&arg);
	return (int)a;
}

int
float__less_than(
	Float	left,
	Float	right)
{
	float	l;
	float	r;

	l = *((float *)&left);
	r = *((float *)&right);
	return l < r;
}

Float
float__log(
	Float	arg)
{
	float	result;
	float	a;

	result = logf(*((float *)&arg));
	return *((Float *)&result);
}

Float
float__minus(
	Float	arg)
{
	float	a;
	float	result;

	a = *((float *)&arg);
	result = -a;
	return *((Float *)&result);
}

Float
float__multiply(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = l * r;
	return *((Float *)&result);

}

Float
float__power(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = powf(l, r);
	/* printf("l=%f r=%f result=%f\n",
	  (double)l, (double)r, (double)result); */
	return *((Float *)&result);
}

Float
float__remainder(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = l * r;
	assert(0);
	return *((Float *)&result);
}

Float
float__rint(
	Float	arg)
{
	float	a;
	float	result;

	a = *((float *)&arg);
	result = rint(a);
	/* (void)printf("float__rint(%f)=>%f\n", a, result); */
	return *((Float *)&result);
}

Float
float__round(
	Float	arg)
{
	extern float roundf(float);
	float	a;
	float	result;

	a = *((float *)&arg);
	result = roundf(a);
	/* (void)printf("float__round(%f)=>%f\n", a, result); */
	return *((Float *)&result);
}

Float
float__sine(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)sin((double)a);
	return *((Float *)&result);
}

Float
float__square_root(
	Float	arg)
{
	float	a;
	float	result;

	a = *((float *)&arg);
	result = (float)sqrt((double)a);
	return *((Float *)&result);
}

Float
float__subtract(
	Float	left,
	Float	right)
{
	float	l;
	float	r;
	float	result;

	l = *((float *)&left);
	r = *((float *)&right);
	result = l - r;
	return *((Float *)&result);
}

Float
float__tangent(
	Float	angle)
{
	float	a;
	float	result;

	a = *((float *)&angle);
	result = (float)tan((double)a);
	return *((Float *)&result);
}

unsigned
float__unsigned_convert(
	Float	arg)
{
	float	a;
	unsigned result;

	a = *((float *)&arg);
	result = (unsigned)a;
	return result;
}


Float
integer__float_convert(
	int	arg)
{
	float	result;

	result = (float)arg;
	return *((Float *)&result);
}

Float16
float16__create(void)
{
	Float16 float16;

	float16 = (Float16)malloc(sizeof *float16);
	float16->floats[0] = (float)0.0;
	float16->floats[1] = (float)0.0;
	float16->floats[2] = (float)0.0;
	float16->floats[3] = (float)0.0;
	float16->floats[4] = (float)0.0;
	float16->floats[5] = (float)0.0;
	float16->floats[6] = (float)0.0;
	float16->floats[7] = (float)0.0;
	float16->floats[8] = (float)0.0;
	float16->floats[9] = (float)0.0;
	float16->floats[10] = (float)0.0;
	float16->floats[11] = (float)0.0;
	float16->floats[12] = (float)0.0;
	float16->floats[13] = (float)0.0;
	float16->floats[14] = (float)0.0;
	float16->floats[15] = (float)0.0;
	return float16;
}


Float
float16__fetch1(
	Float16	float16,
	unsigned index)
{
	float	result;

	assert (index < 16);
	result = float16->floats[index];
	return *((Float *)&result);
}

void
float16__store1(
	Float16	float16,
	unsigned index,
	Float value)
{
	float	v;

	v = *((float *)&value);
	assert (index < 16);
	float16->floats[index] = v;
}

