📄 slarith.c
字号:
/* Copyright (c) 1998, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#include <math.h>#ifdef HAVE_LOCALE_H# include <locale.h>#endif#include "slang.h"#include "_slang.h"/* * This file defines binary and unary operations on all integer types. * Supported types include: * * SLANG_CHAR_TYPE (char) * SLANG_SHORT_TYPE (short) * SLANG_INT_TYPE (int) * SLANG_LONG_TYPE (long) * SLANG_FLOAT_TYPE (float) * SLANG_DOUBLE_TYPE (double) * * as well as unsigned types. The result-type of an arithmentic operation * will depend upon the data types involved. I am going to distinguish * between the boolean operations such as `and' and `or' from the arithmetic * operations such as `plus'. Since the result of a boolean operation is * either 1 or 0, a boolean result will be represented by SLANG_CHAR_TYPE. * Ordinarily I would use an integer but for arrays it makes more sense to * use a character data type. * * So, the following will be assumed (`+' is any arithmetic operator) * * char + char = int * char|short + short = int * char|short|int + int = int * char|short|int|long + long = long * char|short|int|long|float + float = float * char|short|int|long|float|double + double = double * * In the actual implementation, a brute force approach is avoided. Such * an approach would mean defining different functions for all possible * combinations of types. Including the unsigned types, and not including * the complex number type, there are 10 arithmetic types and 10*10=100 * different combinations of types. Clearly this would be too much. * * One approach would be to define binary functions only between operands of * the same type and then convert types as appropriate. This would require * just 6 such functions (int, uint, long, ulong, float, double). * However, many conversion functions are going to be required, particularly * since we are going to allow typecasting from one arithmetic to another. * Since the bit pattern of signed and unsigned types are the same, and only * the interpretation differs, there will be no functions to convert between * signed and unsigned forms of a given type. */#define MAX_ARITHMETIC_TYPES 10unsigned char _SLarith_Arith_Types[] ={ SLANG_CHAR_TYPE, SLANG_UCHAR_TYPE, SLANG_SHORT_TYPE, SLANG_USHORT_TYPE, SLANG_INT_TYPE, SLANG_UINT_TYPE, SLANG_LONG_TYPE, SLANG_ULONG_TYPE, SLANG_FLOAT_TYPE, SLANG_DOUBLE_TYPE, 0};/* Here are a bunch of functions to convert from one type to another. To * facilitate the process, a macros will be used. */#define DEFUN_1(f,from_type,to_type) \static void f (to_type *y, from_type *x, unsigned int n) \{ \ unsigned int i; \ for (i = 0; i < n; i++) y[i] = (to_type) x[i]; \}#define DEFUN_2(f,from_type,to_type,copy_fun) \static VOID_STAR f (VOID_STAR xp, unsigned int n) \{ \ from_type *x; \ to_type *y; \ x = (from_type *) xp; \ if (NULL == (y = (to_type *) SLmalloc (sizeof (to_type) * n))) return NULL; \ copy_fun (y, x, n); \ return (VOID_STAR) y; \}typedef VOID_STAR (*Convert_Fun_Type)(VOID_STAR, unsigned int);DEFUN_1(copy_char_to_char,char,char)#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_char_to_short,char,short)DEFUN_1(copy_char_to_ushort,char,unsigned short)#else# define copy_char_to_short copy_char_to_int# define copy_char_to_ushort copy_char_to_uint#endifDEFUN_1(copy_char_to_int,char,int)DEFUN_1(copy_char_to_uint,char,unsigned int)#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_char_to_long,char,long)DEFUN_1(copy_char_to_ulong,char,unsigned long)#else# define copy_char_to_long copy_char_to_int# define copy_char_to_ulong copy_char_to_uint#endif#if SLANG_HAS_FLOATDEFUN_1(copy_char_to_float,char,float)DEFUN_1(copy_char_to_double,char,double)#endif#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_uchar_to_short,unsigned char,short)DEFUN_1(copy_uchar_to_ushort,unsigned char,unsigned short)#else# define copy_uchar_to_short copy_uchar_to_int# define copy_uchar_to_ushort copy_uchar_to_uint#endifDEFUN_1(copy_uchar_to_int,unsigned char,int)DEFUN_1(copy_uchar_to_uint,unsigned char,unsigned int)#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_uchar_to_long,unsigned char,long)DEFUN_1(copy_uchar_to_ulong,unsigned char,unsigned long)#else# define copy_uchar_to_long copy_uchar_to_int# define copy_uchar_to_ulong copy_uchar_to_uint#endif#if SLANG_HAS_FLOATDEFUN_1(copy_uchar_to_float,unsigned char,float)DEFUN_1(copy_uchar_to_double,unsigned char,double)#endif#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_short_to_char,short,char)DEFUN_1(copy_short_to_uchar,short,unsigned char)DEFUN_1(copy_short_to_short,short,short)DEFUN_1(copy_short_to_int,short,int)DEFUN_1(copy_short_to_uint,short,unsigned int)DEFUN_1(copy_short_to_long,short,long)DEFUN_1(copy_short_to_ulong,short,unsigned long)#if SLANG_HAS_FLOATDEFUN_1(copy_short_to_float,short,float)DEFUN_1(copy_short_to_double,short,double)#endifDEFUN_1(copy_ushort_to_char,unsigned short,char)DEFUN_1(copy_ushort_to_uchar,unsigned short,unsigned char)DEFUN_1(copy_ushort_to_int,unsigned short,int)DEFUN_1(copy_ushort_to_uint,unsigned short,unsigned int)DEFUN_1(copy_ushort_to_long,unsigned short,long)DEFUN_1(copy_ushort_to_ulong,unsigned short,unsigned long)#if SLANG_HAS_FLOATDEFUN_1(copy_ushort_to_float,unsigned short,float)DEFUN_1(copy_ushort_to_double,unsigned short,double)#endif#else# define copy_short_to_char copy_int_to_char# define copy_short_to_uchar copy_int_to_uchar# define copy_short_to_short copy_int_to_int# define copy_short_to_int copy_int_to_int# define copy_short_to_uint copy_int_to_int# define copy_short_to_long copy_int_to_long# define copy_short_to_ulong copy_int_to_ulong#if SLANG_HAS_FLOAT# define copy_short_to_float copy_int_to_float# define copy_short_to_double copy_int_to_double#endif# define copy_ushort_to_char copy_uint_to_char# define copy_ushort_to_uchar copy_uint_to_uchar# define copy_ushort_to_int copy_int_to_int# define copy_ushort_to_uint copy_int_to_int# define copy_ushort_to_long copy_uint_to_long# define copy_ushort_to_ulong copy_uint_to_ulong#if SLANG_HAS_FLOAT# define copy_ushort_to_float copy_uint_to_float# define copy_ushort_to_double copy_uint_to_double#endif#endifDEFUN_1(copy_int_to_char,int,char)DEFUN_1(copy_int_to_uchar,int,unsigned char)DEFUN_1(copy_uint_to_char,unsigned int,char)DEFUN_1(copy_uint_to_uchar,unsigned int,unsigned char)#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_int_to_short,int,short)DEFUN_1(copy_int_to_ushort,int,unsigned short)DEFUN_1(copy_uint_to_short,unsigned int,short)DEFUN_1(copy_uint_to_ushort,unsigned int,unsigned short)#else# define copy_int_to_short copy_int_to_int# define copy_int_to_ushort copy_int_to_int# define copy_uint_to_short copy_int_to_int# define copy_uint_to_ushort copy_int_to_int#endifDEFUN_1(copy_int_to_int,int,int)#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_int_to_long,int,long)DEFUN_1(copy_int_to_ulong,int,unsigned long)DEFUN_1(copy_uint_to_long,unsigned int,long)DEFUN_1(copy_uint_to_ulong,unsigned int,unsigned long)#else# define copy_int_to_long copy_int_to_int# define copy_int_to_ulong copy_int_to_int# define copy_uint_to_long copy_int_to_int# define copy_uint_to_ulong copy_int_to_int#endif#if SLANG_HAS_FLOATDEFUN_1(copy_int_to_float,int,float)DEFUN_1(copy_int_to_double,int,double)DEFUN_1(copy_uint_to_float,unsigned int,float)DEFUN_1(copy_uint_to_double,unsigned int,double)#endif#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_long_to_char,long,char)DEFUN_1(copy_long_to_uchar,long,unsigned char)DEFUN_1(copy_long_to_short,long,short)DEFUN_1(copy_long_to_ushort,long,unsigned short)DEFUN_1(copy_long_to_int,long,int)DEFUN_1(copy_long_to_uint,long,unsigned int)DEFUN_1(copy_long_to_long,long,long)DEFUN_1(copy_ulong_to_char,unsigned long,char)DEFUN_1(copy_ulong_to_uchar,unsigned long,unsigned char)DEFUN_1(copy_ulong_to_short,unsigned long,short)DEFUN_1(copy_ulong_to_ushort,unsigned long,unsigned short)DEFUN_1(copy_ulong_to_int,unsigned long,int)DEFUN_1(copy_ulong_to_uint,unsigned long,unsigned int)#if SLANG_HAS_FLOATDEFUN_1(copy_long_to_float,long,float)DEFUN_1(copy_long_to_double,long,double)DEFUN_1(copy_ulong_to_float,unsigned long,float)DEFUN_1(copy_ulong_to_double,unsigned long,double)#endif#else#define copy_long_to_char copy_int_to_char#define copy_long_to_uchar copy_int_to_uchar#define copy_long_to_short copy_int_to_short#define copy_long_to_ushort copy_int_to_ushort#define copy_long_to_int copy_int_to_int#define copy_long_to_uint copy_int_to_int#define copy_long_to_long copy_int_to_int#define copy_long_to_float copy_int_to_float#define copy_long_to_double copy_int_to_double#define copy_ulong_to_char copy_uint_to_char#define copy_ulong_to_uchar copy_uint_to_uchar#define copy_ulong_to_short copy_uint_to_short#define copy_ulong_to_ushort copy_uint_to_ushort#define copy_ulong_to_int copy_int_to_int#define copy_ulong_to_uint copy_int_to_int#define copy_ulong_to_float copy_uint_to_float#define copy_ulong_to_double copy_uint_to_double#endif#if SLANG_HAS_FLOATDEFUN_1(copy_float_to_char,float,char)DEFUN_1(copy_float_to_uchar,float,unsigned char)#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_float_to_short,float,short)DEFUN_1(copy_float_to_ushort,float,unsigned short)#else# define copy_float_to_short copy_float_to_int# define copy_float_to_ushort copy_float_to_uint#endifDEFUN_1(copy_float_to_int,float,int)DEFUN_1(copy_float_to_uint,float,unsigned int)#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_float_to_long,float,long)DEFUN_1(copy_float_to_ulong,float,unsigned long)#else# define copy_float_to_long copy_float_to_int# define copy_float_to_ulong copy_float_to_uint#endifDEFUN_1(copy_float_to_float,float,float)static void copy_float_to_double (double *y, float *x, unsigned int n) { unsigned int i; for (i = 0; i < n; i++) y[i] = (double) x[i]; }/* DEFUN_1(copy_float_to_double,float,double) */DEFUN_1(copy_double_to_char,double,char)DEFUN_1(copy_double_to_uchar,double,unsigned char)#if SIZEOF_INT != SIZEOF_SHORTDEFUN_1(copy_double_to_short,double,short)DEFUN_1(copy_double_to_ushort,double,unsigned short)#else# define copy_double_to_short copy_double_to_int# define copy_double_to_ushort copy_double_to_uint#endifDEFUN_1(copy_double_to_int,double,int)DEFUN_1(copy_double_to_uint,double,unsigned int)#if SIZEOF_INT != SIZEOF_LONGDEFUN_1(copy_double_to_long,double,long)DEFUN_1(copy_double_to_ulong,double,unsigned long)#else# define copy_double_to_long copy_double_to_int# define copy_double_to_ulong copy_double_to_uint#endifDEFUN_1(copy_double_to_float,double,float)DEFUN_1(copy_double_to_double,double,double)#endif /* SLANG_HAS_FLOAT */ DEFUN_2(char_to_int,char,int,copy_char_to_int)DEFUN_2(char_to_uint,char,unsigned int,copy_char_to_uint)#if SIZEOF_INT != SIZEOF_LONGDEFUN_2(char_to_long,char,long,copy_char_to_long)DEFUN_2(char_to_ulong,char,unsigned long,copy_char_to_ulong)#else# define char_to_long char_to_int# define char_to_ulong char_to_uint#endif#if SLANG_HAS_FLOATDEFUN_2(char_to_float,char,float,copy_char_to_float)DEFUN_2(char_to_double,char,double,copy_char_to_double)#endifDEFUN_2(uchar_to_int,unsigned char,int,copy_uchar_to_int)DEFUN_2(uchar_to_uint,unsigned char,unsigned int,copy_uchar_to_uint)#if SIZEOF_INT != SIZEOF_LONGDEFUN_2(uchar_to_long,unsigned char,long,copy_uchar_to_long)DEFUN_2(uchar_to_ulong,unsigned char,unsigned long,copy_uchar_to_ulong)#else# define uchar_to_long uchar_to_int# define uchar_to_ulong uchar_to_uint#endif#if SLANG_HAS_FLOATDEFUN_2(uchar_to_float,unsigned char,float,copy_uchar_to_float)DEFUN_2(uchar_to_double,unsigned char,double,copy_uchar_to_double)#endif#if SIZEOF_INT != SIZEOF_SHORTDEFUN_2(short_to_int,short,int,copy_short_to_int)DEFUN_2(short_to_uint,short,unsigned int,copy_short_to_uint)DEFUN_2(short_to_long,short,long,copy_short_to_long)DEFUN_2(short_to_ulong,short,unsigned long,copy_short_to_ulong)#if SLANG_HAS_FLOATDEFUN_2(short_to_float,short,float,copy_short_to_float)DEFUN_2(short_to_double,short,double,copy_short_to_double)#endifDEFUN_2(ushort_to_int,unsigned short,int,copy_ushort_to_int)DEFUN_2(ushort_to_uint,unsigned short,unsigned int,copy_ushort_to_uint)DEFUN_2(ushort_to_long,unsigned short,long,copy_ushort_to_long)DEFUN_2(ushort_to_ulong,unsigned short,unsigned long,copy_ushort_to_ulong)#if SLANG_HAS_FLOATDEFUN_2(ushort_to_float,unsigned short,float,copy_ushort_to_float)DEFUN_2(ushort_to_double,unsigned short,double,copy_ushort_to_double)#endif#else# define short_to_int NULL# define short_to_uint NULL# define short_to_long int_to_long# define short_to_ulong int_to_ulong#if SLANG_HAS_FLOAT# define short_to_float int_to_float# define short_to_double int_to_double#endif# define ushort_to_int NULL# define ushort_to_uint NULL# define ushort_to_long uint_to_long# define ushort_to_ulong uint_to_ulong#if SLANG_HAS_FLOAT# define ushort_to_float uint_to_float# define ushort_to_double uint_to_double#endif#endif#if SIZEOF_INT != SIZEOF_LONGDEFUN_2(int_to_long,int,long,copy_int_to_long)DEFUN_2(int_to_ulong,int,unsigned long,copy_int_to_ulong)#else# define int_to_long NULL# define int_to_ulong NULL#endif#if SLANG_HAS_FLOATDEFUN_2(int_to_float,int,float,copy_int_to_float)DEFUN_2(int_to_double,int,double,copy_int_to_double)#endif#if SIZEOF_INT != SIZEOF_LONGDEFUN_2(uint_to_long,unsigned int,long,copy_uint_to_long)DEFUN_2(uint_to_ulong,unsigned int,unsigned long,copy_uint_to_ulong)#else# define uint_to_long NULL# define uint_to_ulong NULL#endif#if SLANG_HAS_FLOATDEFUN_2(uint_to_float,unsigned int,float,copy_uint_to_float)DEFUN_2(uint_to_double,unsigned int,double,copy_uint_to_double)#if SIZEOF_INT != SIZEOF_LONGDEFUN_2(long_to_float,long,float,copy_long_to_float)DEFUN_2(long_to_double,long,double,copy_long_to_double)DEFUN_2(ulong_to_float,unsigned long,float,copy_ulong_to_float)DEFUN_2(ulong_to_double,unsigned long,double,copy_ulong_to_double)#else# define long_to_float int_to_float# define long_to_double int_to_double# define ulong_to_float uint_to_float# define ulong_to_double uint_to_double#endifDEFUN_2(float_to_double,float,double,copy_float_to_double)#define TO_DOUBLE_FUN(name,type) \static double name (VOID_STAR x) { return (double) *(type *) x; }TO_DOUBLE_FUN(char_to_one_double,char)TO_DOUBLE_FUN(uchar_to_one_double,unsigned char)#if SIZEOF_INT != SIZEOF_SHORTTO_DOUBLE_FUN(short_to_one_double,short)TO_DOUBLE_FUN(ushort_to_one_double,unsigned short)#else# define short_to_one_double int_to_one_double# define ushort_to_one_double uint_to_one_double#endifTO_DOUBLE_FUN(int_to_one_double,int)TO_DOUBLE_FUN(uint_to_one_double,unsigned int)#if SIZEOF_INT != SIZEOF_LONGTO_DOUBLE_FUN(long_to_one_double,long)TO_DOUBLE_FUN(ulong_to_one_double,unsigned long)#else# define long_to_one_double int_to_one_double# define ulong_to_one_double uint_to_one_double
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -