diff options
Diffstat (limited to 'src/sffe')
-rw-r--r-- | src/sffe/About | 4 | ||||
-rw-r--r-- | src/sffe/Makefile.in | 36 | ||||
-rw-r--r-- | src/sffe/asm/build.sh | 3 | ||||
-rw-r--r-- | src/sffe/asm/build_win.sh | 3 | ||||
-rw-r--r-- | src/sffe/asm/cmplx.asm | 901 | ||||
-rw-r--r-- | src/sffe/sffe.c | 1013 | ||||
-rw-r--r-- | src/sffe/sffe.pri | 23 | ||||
-rw-r--r-- | src/sffe/sffe_cmplx_asm.c | 331 | ||||
-rw-r--r-- | src/sffe/sffe_cmplx_gsl.c | 294 |
9 files changed, 2608 insertions, 0 deletions
diff --git a/src/sffe/About b/src/sffe/About new file mode 100644 index 0000000..bea0456 --- /dev/null +++ b/src/sffe/About @@ -0,0 +1,4 @@ +SFFE ( Segfautlabs Formula Evaluator ) +sffe is very fast complex math formula evaluator written in C. +you can read more about sffe lib at + http://www.segfaultlabs.com/projects/sffe diff --git a/src/sffe/Makefile.in b/src/sffe/Makefile.in new file mode 100644 index 0000000..6d1f565 --- /dev/null +++ b/src/sffe/Makefile.in @@ -0,0 +1,36 @@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LIBS = @LIBS@ +LFLAGS = @LDFLAGS@ +AR = @AR@ +RANLIB = @RANLIB@ + +SRCS = sffe.c \ + sffe_cmplx_asm.c \ + sffe_cmplx_gsl.c + +OBJS = $(SRCS:.c=.o) @ASM_CMPLX_O@ + +TLIB = ../lib/libsffe.a + +all: $(TLIB) + +asm/cmplx.o: asm/cmplx.asm + nasm -f @CMPLX_O_TARGET@ asm/cmplx.asm -oasm/cmplx.o + +$(TLIB):$(OBJS) + rm -f $@ + $(AR) rc $@ $(OBJS) @ASM_CMPLX_O@ + $(RANLIB) $@ + +keywords.c: keywords.gperf + gperf -t -p -D -C -a keywords.gperf > keywords.c + +clean: + rm -f $(TLIB) + rm -f *.[oas] asm/*.o + rm -f *~ + rm -f core + +distclean:clean + rm Makefile diff --git a/src/sffe/asm/build.sh b/src/sffe/asm/build.sh new file mode 100644 index 0000000..9c0f362 --- /dev/null +++ b/src/sffe/asm/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash +nasm -f elf cmplx.asm -ocmplx.o +# Not used anymore because ../Makefile already contains this compilation. diff --git a/src/sffe/asm/build_win.sh b/src/sffe/asm/build_win.sh new file mode 100644 index 0000000..8f1214b --- /dev/null +++ b/src/sffe/asm/build_win.sh @@ -0,0 +1,3 @@ +#!/bin/bash +nasm -f coff cmplx.asm -ocmplx.o +# Not used anymore because ../Makefile already contains this compilation. diff --git a/src/sffe/asm/cmplx.asm b/src/sffe/asm/cmplx.asm new file mode 100644 index 0000000..ea3826b --- /dev/null +++ b/src/sffe/asm/cmplx.asm @@ -0,0 +1,901 @@ + ; COMPLEX NUMBER ARITHMETICS + ; Mateusz Malczak + ; NASM version + ; http://www.malczak.info + ; SFFE libs + ; http://segfaultlabs.com/projects/sffe + global _sffecabs,_sffecarg,_sffecargs,_sffecargc + global _sffecinv + global _sffecexp,_sffecln,_sffeclog2,_sffeclog + global _sffecsin,_sffeccos,_sffecsincos,_sffectan,_sffeccot + global _sffecsinh,_sffeccosh,_sffectanh,_sffeccoth + global _sffeccpow, _sffecpowd, _sffecpowi, _sffecpowc + global _sffecsqrt, _sffecrtni + + %ifndef DELPHI + ; section .text use32 class=CODE ;class=CODE - needed for Borlands Compiler + + ; section CODE use32 + ; ".text" is more portable than "CODE use32": + section .text + %endif + + ;; internal use +%ifdef DELPHI +[section expfunc_text use32] +%endif +_sffecexpfnc: ; exponent of real argument + fldl2e + fmulp st1 + fld st0 + frndint + fsub to st1 + fld1 + fscale + fstp st1 + fxch st1 + f2xm1 + fld1 + faddp st1 + fmulp st1 + ret + + ;; globals +%ifdef DELPHI +[section cabs_text use32] +%endif +_sffecabs: + push ebp + mov ebp, esp + fld qword [ebp+08h] + fmul qword [ebp+08h] + fld qword [ebp+10h] + fmul qword [ebp+10h] + faddp st1 + fsqrt + leave + ret + +%ifdef DELPHI +[section carg_text use32] +%endif +_sffecarg: + push ebp + mov ebp, esp + fld qword [ebp+08h] + fld qword [ebp+10h] + fpatan + wait + leave + ret + +%ifdef DELPHI +[section cargs_text use32] +%endif +_sffecargs: + push ebp + mov ebp, esp + fld qword [ebp+10h] + fld qword [ebp+08h] + fmul qword [ebp+08h] + fld qword [ebp+10h] + fmul qword [ebp+10h] + faddp st1 + fsqrt + fdivp st1 + wait + leave + ret + +%ifdef DELPHI +[section cargc_text use32] +%endif +_sffecargc: + push ebp + mov ebp, esp + fld qword [ebp+08h] + fld qword [ebp+08h] + fmul qword [ebp+08h] + fld qword [ebp+10h] + fmul qword [ebp+10h] + faddp st1 + fsqrt + fdivp st1 + wait + leave + ret + +%ifdef DELPHI +[section cinv_text use32] +%endif +_sffecinv: + push ebp + mov ebp, esp + mov edx, [ebp+08h] + fld qword [ebp+0ch] + fld qword [ebp+14h] + fld st0 + fmul to st0 + fld st2 + fmul to st0 + faddp st1 + fdiv to st1 + fdiv to st2 + fstp st0 + fchs + fstp qword [edx+08h] + fstp qword [edx] + wait + leave + ret + +%ifdef DELPHI +[section cexp_text use32] +%endif +_sffecexp: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + fld qword [ebp+0ch] + call _sffecexpfnc + fld qword [ebp+14h] + fsincos + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + wait + leave + ret + +%ifdef DELPHI +[section cln_text use32] +%endif +_sffecln: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ;ln||z|| + fld1 + fxch st1 + fyl2x + fldl2e + fdivp st1 + fstp qword [eax] + fstp qword [eax+08h] + wait + leave + ret + +%ifdef DELPHI +[section clog2_text use32] +%endif +_sffeclog2: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + fld1 + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + fyl2x + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + fldln2 + fdivp st1 + fstp qword [eax+08h] + fstp qword [eax] + wait + leave + ret + +%ifdef DELPHI +[section clog_text use32] +%endif +_sffeclog: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;ln(base) + fld1 + fild word [ebp+1ch] + fyl2x + fldl2e + fdivp st1 + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ;ln||z|| + fld1 + fxch st1 + fyl2x + fldl2e + fdivp st1 + fdiv st1 + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + fdiv st2 + fstp qword [eax+08h] + fstp qword [eax] + fstp st0 + wait + leave + ret + +%ifdef DELPHI +[section csin_text use32] +%endif +_sffecsin: + push ebp + mov ebp, esp + mov eax, [ebp+08h] + fld1 + fld1 + faddp st1 + fld qword [ebp+14h] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1;- + fld st1;- optimize + faddp st1;- + fdiv st3 + fxch st2 + fxch st1 + fsubp st1 + fdiv st2 + fld qword [ebp+0ch] + fsincos + fxch st3 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + fstp st0 + fwait + leave + ret + +%ifdef DELPHI +[section ccos_text use32] +%endif +_sffeccos: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + fld1 + fld1 + faddp st1 + fld qword [ebp+14h] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + faddp st1 + fdiv st3 + fxch st2 + fxch st1 + fsubp st1 + fdiv st2 + fld qword [ebp+0ch] + fsincos + fxch st2 + fmulp st1 + fchs + fstp qword [eax+08h] + fmulp st1 + fstp qword [eax] + fstp st0 + fwait + leave + ret + +%ifdef DELPHI +[section ctan_text use32] +%endif +_sffectan: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;sinh(2b) cosh(2b) + fld1 + fld1 + faddp st1 + fld qword [ebp+14h] + fadd qword [ebp+14h] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + faddp st1 + fdiv st3 + fxch st2 + fxch st1 + fsubp st1 + fdivrp st2 ;fdivrp st(2),st(0) + ;sin(2b) cos(2b) + fld qword [ebp+0ch] + fadd qword [ebp+0ch] + fsincos + faddp st2 + ;check if zero + fdiv st1 + fstp qword [eax] + fdivp st1 + fstp qword [eax+08h] + fwait + leave + ret + +%ifdef DELPHI +[section ccot_text use32] +%endif +_sffeccot: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;sinh(2b) cosh(2b) + fld1 + fld1 + faddp st1 + fld qword [ebp+14h] + fadd qword [ebp+14h] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + fsubp st1 + fdiv st3 + fxch st2 + fxch st1 + faddp st1 + fdivrp st2 ;fdivrp st(2),st(0) + ;sin(2b) cos(2b) + fld qword [ebp+0ch] + fld st0 + faddp st1 + fsincos + fsubp st3 + ;check if zero + fdiv st2 + fstp qword [eax] + fdiv st1 + fchs + fstp qword [eax+08h] + fstp st0 + fwait + leave + ret + +%ifdef DELPHI +[section csinh_text use32] +%endif +_sffecsinh: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + fld1 + fld1 + faddp st1 + fld qword [ebp+0Ch] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + faddp st1 + fdiv st3 + fxch st2 + fxch st1 + fsubp st1 + fdivrp st2 ;jak w tan i cot + fld qword [ebp+14h] + fsincos + fxch st2 + fmulp st1 + fstp qword [eax+08h] + fmulp st1 + fstp qword [eax] + fwait + leave + ret + +%ifdef DELPHI +[section ccosh_text use32] +%endif +_sffeccosh: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + fld qword [ebp+0ch] + call _sffecexpfnc + fld st0 + fld1 + fxch st1 + fdivp st1 + fld st1 + fld st1 + faddp st1 + fld1 + fld1 + faddp st1 + fdivp st1 + fxch st2 + fxch st1 + fsubp st1 + fld1 + fld1 + faddp st1 + fdivp st1 + fld qword [ebp+14h] + fsincos + fxch st2 + fmulp st1 + fstp qword [eax+08h] + fmulp st1 + fstp qword [eax] + fwait + leave + ret + +%ifdef DELPHI +[section ctanh_text use32] +%endif +_sffectanh: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;sinh(2a) cosh(2a) + fld1 + fld1 + faddp st1 + fld qword [ebp+0ch] + fadd qword [ebp+0ch] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + fsubp st1 + fdiv st3 + fxch st2 + fxch st1 + faddp st1 + fdivrp st2 ;jak wczesniej + ;sin(2b) cos(2b) + fld qword [ebp+14h] + fadd qword [ebp+14h] + fsincos + faddp st3 + ;check if zero + fdiv st2 + fstp qword [eax+08h] + fxch st1 + fdivp st1 + fstp qword [eax] + fwait + leave + ret + +%ifdef DELPHI +[section ccoth_text use32] +%endif +_sffeccoth: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + ;sinh(2b) cosh(2b) + fld1 + fld1 + faddp st1 + fld qword [ebp+0ch] + fadd qword [ebp+0ch] + call _sffecexpfnc + fld1 + fdiv st1 + fld st1 + fld st1 + fsubp st1 + fdiv st3 + fxch st2 + fxch st1 + faddp st1 + fdivrp st2 ;jak wczesniej + ;sin(2b) cos(2b) + fld qword [ebp+14h] + fadd qword [ebp+14h] + fsincos + fsubp st3 + ;check if zero + fdiv st2 + fchs + fstp qword [eax+08h] + fxch st1 + fdivp st1 + fstp qword [eax] + fwait + leave + ret + +;***************** COMPLEX TO COMPLEX POWER +%ifdef DELPHI +[section ccpow_text use32] +%endif +_sffeccpow: +;TODO: wyeliminowac xch po wystepujace po obliczeniu theta + push ebp + mov ebp,esp + fld1 + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ftst + fstsw ax + test ah, 1000000b + jnz MZ + mov eax, [ebp+08h] + ;ln||z||*/ + fyl2x + fldl2e + fdivp st1 + ;theta*/ + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + + fld st1 ;ln||z|| + fmul qword [ebp+1ch] + fld st1 ;theta + fmul qword [ebp+24h] + fsubp st1 ; st0-st1 + fxch st2 ; w st2 mam teraz a = z2.re * lnz - z2.im * theta w st0 jest ln||z|| + fmul qword [ebp+24h] + fxch st1 + fmul qword [ebp+1ch] + faddp st1 + fxch st1 + + call _sffecexpfnc + fxch st1 + fsincos + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + jmp END +MZ: + mov eax, [ebp+08h] + fstp qword [eax+08h] + fldz + fstp qword [eax] + fstp st0 +END: +s fwait + leave + ret + +;***************** COMPLEX TO REAL POWER +%ifdef DELPHI +[section cpowd_text use32] +%endif +_sffecpowd: + push ebp + mov ebp,esp +; fld1 + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ftst + fstsw ax + test ah, 1000000b + jnz MZ2 + mov eax, [ebp+08h] + fld1 + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + fmul qword [ebp+1ch] + fxch st2 + ;ln||z|| + fyl2x + fldl2e + fdivp st1 + fmul qword [ebp+1ch] + + call _sffecexpfnc + fxch st1 + fsincos + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + jmp END2 +MZ2: + mov eax, [ebp+08h] + fstp qword [eax+08h] + fldz + fstp qword [eax] +END2: + fwait + leave + ret + +;***************** COMPLEX TO INT POWER +%ifdef DELPHI +[section cpowi_text use32] +%endif +_sffecpowi: + push ebp + mov ebp,esp + ;z module + fild dword [ebp+1ch] ;st(0)=n + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ftst + fstsw ax + test ah, 1000000b + jnz MZ5 + mov eax, [ebp+08h] + ;||z||^n + fld1 + fxch st1 + fyl2x + fmulp st1 + fld st0 + frndint + fsub to st1 + fld1 + fscale + fstp st1 + fxch st1 + f2xm1 + fld1 + faddp st1 + fmulp st1 + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan + fild dword [ebp+1ch] + fmulp st1 + fsincos + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + jmp END53 +MZ5: + mov eax, [ebp+08h] + fstp qword [eax+08h] + fldz + fstp qword [eax] + fstp st0 +END53: + fwait + leave + ret + +;***************** INT/DOUBLE TO COMPLEX POWER +%ifdef DELPHI +[section cpowc_text use32] +%endif +_sffecpowc: + push ebp + mov ebp,esp + fld qword [ebp+0ch] + ftst + fstsw ax + test ah, 1000000b + jnz MZ3 + mov eax, [ebp+08h] + ;n^a + fld qword [ebp+14h] + fxch st1 + fabs + fld1 + fxch st1 + fyl2x + fmulp st1 + fld st0 + frndint + fsub to st1 + fld1 + fscale + fstp st1 + fxch st1 + f2xm1 + fld1 + faddp st1 + fmulp st1 + ;ln||n|| + fld qword [ebp+0ch] + fabs + fld1 + fxch st1 + fyl2x + fldl2e + fdivp st1 + fld qword [ebp+1ch] + fmulp st1 + fsincos + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + jmp END3 +MZ3: + mov eax, [ebp+08h] + fstp qword [eax+08h] + fldz + fstp qword [eax] +END3: + fwait + leave + ret + +;***************** SQRT +%ifdef DELPHI +[section csqrt_text use32] +%endif +_sffecsqrt: + push ebp + mov ebp,esp + push ebx + mov ebx, [ebp+08h] + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + fld st0 ;duplicate |z| + ;real + fadd qword [ebp+0ch] + fld1 + fld1 + faddp st1 + fdivp st1 + fsqrt + fstp qword [ebx] + fwait + ;imag + fsub qword [ebp+0ch] + fld1 + fld1 + faddp st1 + fdivp st1 + fsqrt + ;imag sign check + push eax + fld qword [ebp+14h] + ftst + fstp st0 + fstsw ax + test ah, 1b + jz IMAGPOS + fchs +IMAGPOS: + pop eax + fwait + fstp qword [ebx+08h] + pop ebx + leave + ret + +;***************** Nth ORDER ROOT +%ifdef DELPHI +[section crtni_text use32] +%endif +_sffecrtni: + push ebp + mov ebp,esp + ;z module + fld qword [ebp+0ch] + fmul qword [ebp+0ch] + fld qword [ebp+14h] + fmul qword [ebp+14h] + faddp st1 + fsqrt + ftst + fstsw ax + test ah, 1000000b + jnz MZ4 + mov eax, [ebp+08h] + ;n-th root if ||z|| + fld1 + fild word [ebp+1ch] + fdivp st1 ;st0=1/n + fxch st1 ;st0=||z|| st1=1/n + fyl2x ;log2(||z||/n) + fld st0 ;duplikuj st0 + frndint + fsub to st1 ;st0=int( log2(||z||/n) ) st1=frac( log2(||z||/n) ) + fld1 ;st0=1 + fscale ;st0=2^int( log2(||z||/n) ) st1=frac( log2(||z||/n) ) + fstp st1 + fxch st1 + f2xm1 ;st1=2^frac( log2(||z||/n) )-1 + fld1 + faddp st1 + fmulp st1 ;sqrt(||z||) + ;theta + fld qword [ebp+14h] + fld qword [ebp+0ch] + fpatan ;st0=theta st1=sqrN(||z||) + ;theta_i + fldpi + fldpi + faddp st1 ;st0=2Pi st1=theta st2=sqrN(||z||) + fimul word [ebp+20h] + faddp st1 ;st1=theta+i2Pi + fidiv word [ebp+1ch] ;st0=theta_i + ;re/im + fsincos + + fld st2 + fmulp st1 + fstp qword [eax] + fmulp st1 + fstp qword [eax+08h] + jmp END4 +MZ4: + fldz + fstp qword [eax] + fstp qword [eax+08h] +END4: + leave + ret + +%ifndef DELPHI +_sffecfunc: + push ebp + mov ebp,esp + mov eax, [ebp+08h] + leave + ret +%endif diff --git a/src/sffe/sffe.c b/src/sffe/sffe.c new file mode 100644 index 0000000..668893e --- /dev/null +++ b/src/sffe/sffe.c @@ -0,0 +1,1013 @@ +/*///////////////////////////////////////////////////////////////////////////////////// +// project : sFFe ( SegFault (or Segmentation Fault :) ) formula evalutaor ) +// author : Mateusz Malczak ( mateusz@malczak.info ) +// wpage : www.segfaultlabs.com/projects/sffe +/////////////////////////////////////////////////////////////////////////////////////// +// special build for XaoS, for more info visit +// http://www.segfaultlabs.com/projects/sfXaos +/////////////////////////////////////////////////////////////////////////////////////*/ + +#include <config.h> +#ifdef SFFE_USING + +#include <stdlib.h> +#include <stdio.h> +#ifdef linux +#include <ctype.h> +#endif +#include <string.h> + +#include "sffe.h" +#ifdef SFFE_CMPLX_ASM +#include "sffe_cmplx_asm.h" +#elif SFFE_CMPLX_GSL +#include "sffe_cmplx_gsl.h" +#endif + +#define sfset(arg,val) {\ + (arg)->value = (sfNumber*)malloc(sizeof(sfNumber));\ + if ( (arg)->value ) cmplxset( *((arg)->value), (val),0 ); } + +#define sfvar(p,parser,idx) (p)->value = (sfNumber*)((parser)->vars+idx) + +/************************* custom function */ +/* all used in this section variables are defined depanding on complex number realization */ +sffunction *sffe_function(char *fn, size_t len) +{ + unsigned char idx; + for (idx = 5; idx < sffnctscount; idx += 1) /* sffnctscount - defined in sffe_cmplx_* file */ + if (!strncmp(fn, sfcmplxfunc[idx].name, len)) + return (sffunction *) (sfcmplxfunc + idx); + return NULL; +}; + +sffunction *sffe_operator(char op) +{ + switch (op) { + case '^': + return (sffunction *) sfcmplxfunc; + break; + case '+': + return (sffunction *) sfcmplxfunc + 1; + break; + case '-': + return (sffunction *) sfcmplxfunc + 2; + break; + case '*': + return (sffunction *) sfcmplxfunc + 3; + break; + case '/': + return (sffunction *) sfcmplxfunc + 4; + break; + }; + return NULL; +}; + +void *sffe_const(char *fn, size_t len, void *ptr) +{ + unsigned char idx = 3; + for (idx = 0; idx < sfvarscount; idx += 1) + if (!strncmp(fn, sfcnames[idx], len)) { + sfcvals[idx] ((sfNumber *) ptr); + return ptr; + }; + return NULL; +}; + +/************************* custom function */ + + +sffe *sffe_alloc(void) +{ + sffe *rp = (sffe *) malloc(sizeof(sffe)); + if (!rp) + return NULL; + memset(rp, 0, sizeof(sffe)); + return rp; +}; + +static void sffe_clear(sffe ** parser) +{ + sffe *p = *parser; + unsigned int i = 0, j; + for (; i < p->argCount; i++) { + for (j = 0; j < p->varCount; j++) + if (p->args[i].value == p->varPtrs[j]) + j = p->varCount; + if (j == p->varCount) + if (p->args[i].value) + free(p->args[i].value); + }; + if (p->expression) + free(p->expression); + if (p->args) + free(p->args); + if (p->oprs) + free(p->oprs); + p->expression = NULL; + p->args = NULL; + p->oprs = NULL; +}; + +void sffe_free(sffe ** parser) +{ + sffe_clear(parser); + if ((*parser)->userf) + free((*parser)->userf); + if ((*parser)->varChars) + free((*parser)->varChars); + if ((*parser)->varPtrs) + free((*parser)->varPtrs); + free(*parser); + parser = NULL; +}; + +/* not really used, marked to remove +void sffe_eval2(sffe *const parser) +{ + register sfopr* optro; + register sfopr* optr = parser->oprs; + register sfopr* optrl = parser->oprs+parser->oprCount; + optro = optr; + for ( optr=optr; optr!=optrl; optr+=1, optro+=1 ) + { + optro->arg->parg = optro->arg-1; + optr->arg->parg = optr->f( optr->arg )->parg; + }; +};*/ + +sfNumber sffe_eval(sffe * const parser) +{ + register sfopr *optro; + register sfopr *optr = parser->oprs; + register sfopr *optrl = parser->oprs + parser->oprCount; + optro = optr; + for (optr = optr; optr != optrl; optr += 1, optro += 1) { + optro->arg->parg = optro->arg - 1; + optr->arg->parg = optr->f(optr->arg)->parg; + }; + return *(parser->result); +}; + +void *sffe_regvar(sffe ** parser, sfNumber * vptrs, char vchars) +{ + unsigned int i = (*parser)->varCount; + (*parser)->varCount += 1; + (*parser)->varPtrs = + (sfNumber **) realloc((*parser)->varPtrs, + (*parser)->varCount * sizeof(sfNumber *)); + if (!(*parser)->varPtrs) + return NULL; + (*parser)->varChars = + (char *) realloc((*parser)->varChars, (*parser)->varCount); + if (!(*parser)->varChars) + return NULL; + (*parser)->varPtrs[i] = vptrs; + (*parser)->varChars[i] = toupper(vchars); + return (void *) ((*parser)->varPtrs + i); +}; + +void *sffe_regvars(sffe ** parser, unsigned int cN, sfNumber ** vptrs, + char *vchars) +{ + unsigned int i = (*parser)->varCount; + (*parser)->varCount += cN; + (*parser)->varPtrs = + (sfNumber **) realloc((*parser)->varPtrs, + (*parser)->varCount * sizeof(sfNumber *)); + if (!(*parser)->varPtrs) + return NULL; + (*parser)->varChars = + (char *) realloc((*parser)->varChars, (*parser)->varCount); + if (!(*parser)->varChars) + return NULL; + for (cN = 0; i < (*parser)->varCount; i += 1, cN += 1) { + (*parser)->varPtrs[i] = vptrs[cN]; + (*parser)->varChars[i] = toupper(vchars[cN]); + }; + return (void *) ((*parser)->varPtrs + i); +}; + +sfNumber *sffe_varptr(sffe * const parser, char vchar) +{ + unsigned int i = 0; + while (i < parser->varCount) { + if (parser->varChars[i] == vchar) + return parser->varPtrs[i]; + i += 1; + }; + return NULL; +}; + +sfNumber *sffe_setvar(sffe ** parser, sfNumber * vptrs, char vchars) +{ + unsigned int i = 0; + while (i < (*parser)->varCount) { + if ((*parser)->varChars[i] == vchars) { + sfNumber *ret = (*parser)->varPtrs[i]; + (*parser)->varPtrs[i] = vptrs; + return ret; + }; + i += 1; + }; + return NULL; +}; + +void *sffe_regfunc(sffe ** parser, char *vname, unsigned int parcnt, + sffptr funptr) +{ + sffunction *sff; + unsigned short i; + (*parser)->userf = + (sffunction *) realloc((*parser)->userf, + ((*parser)->userfCount + + 1) * sizeof(sffunction)); + if (!(*parser)->userf) + return NULL; + sff = (*parser)->userf + (*parser)->userfCount; + /* 2.XI.2007 changed to get rid of warinings */ + strcpy(sff->name, vname); + /* sff->name = (char*)malloc( strlen(vname) ); */ + for (i = 0; i < strlen(vname); i += 1) + sff->name[i] = (char) toupper((int) vname[i]); + sff->parcnt = parcnt; + sff->fptr = funptr; + (*parser)->userfCount += 1; + return (void *) sff; +}; + +void *sffe_variable(sffe * const p, char *fname, size_t len) +{ + unsigned int idx = 0; + if (len == 1) /*FIXME vars names with length > 1 should be allowed */ + for (; idx < p->varCount; idx += 1) + /* if ( !strncmp(fname,p->varChars[idx],len) ) */ + if (p->varChars[idx] == *fname) + return (void *) p->varPtrs[idx]; + return NULL; +}; + +sffunction *userfunction(const sffe * const p, char *fname, size_t len) +{ + unsigned char idx; + for (idx = 0; idx < p->userfCount; idx += 1) + if (!strncmp(fname, p->userf[idx].name, len)) + return (sffunction *) (p->userf + idx); + return NULL; +}; + +char sffe_donum(char **str) +{ /* parse number in format [-+]ddd[.dddd[e[+-]ddd]] */ + unsigned char flag = 0; /*bit 1 - dot, bit 2 - dec, bits 3,4 - stan, bits 5..8 - error */ + if (**str == '-') { + flag = 0x80; + *str += 1; + }; + if (**str == '+') + *str += 1; + while (!((flag >> 4) & 0x07)) { + switch ((flag & 0x0f) >> 2) { + case 0: /*0..9 */ + while (isdigit(**str)) + *str += 1; + switch (**str) { /*only '.' or 'E' allowed */ + case '.': + flag = (flag & 0xf3) | 4; + break; + case 'E': + flag = (flag & 0xf3) | 8; + break; + default: + flag = 0x10; + }; + break; + case 1: /*. */ + if (flag & 0x03) + flag = 0x20; + else + *str += 1; /*no 2nd dot, no dot after E */ + flag = (flag & 0xf2) | 0x01; + break; + case 2: /*e */ + if (flag & 0x02) + flag = 0x30; + else + *str += 1; /*no 2nd E */ + if (!isdigit(**str)) { /*after E noly [+-] allowed */ + if (**str != '-' && **str != '+') + flag = 0x40; + else + *str += 1; + }; + flag = (flag & 0xf1) | 0x02; + break; + }; + }; + if (flag & 0x80) + flag ^= 0x80; + return flag >> 4; +}; + +char sffe_docmplx(char **str, sfarg ** arg) +{ /* parse complex number in format { [-+]ddd[.dddd[e[+-]ddd]] ; [-+]ddd[.dddd[e[+-]ddd]] } */ + char *chr, *chi; + chr = *str; + if (sffe_donum(str) > 1) + return 1; + if (*(*str)++ != ';') + return 2; + chi = *str; + if (sffe_donum(str) > 1) + return 1; + if (*(*str)++ != '}') + return 2; + + cmplxset(*(*arg)->value, atof(chr), atof(chi)); + return 0; +}; + +char sffe_doname(char **str) +{ + do { + *str += 1; + } while (isalnum(**str) || **str == '_'); + if (strchr("+-*/^~!@#$%&<>?\\:\"|", (int) **str)) + return 1; /*punctator */ + if (**str == '(') + return 2; /* ( - funkcja */ + if (**str == '.') + return 3; /*error :( this means something like X. COS. PI. */ + return 1; +}; + +int sffe_parse(sffe ** parser, char *expression) +{ +/**************var area */ + struct opstack__ { +#ifdef SFFE_DEVEL + char c; /* used in debug build to store operator character */ +#endif + unsigned char t; /* store priority of the operator 'f' */ + sffptr f; + }; + struct stack__ { + struct opstack__ *stck; + unsigned int size; //number of items on stack + struct stack__ *prev; + } *stmp, *stack; + sffunction **fnctbl; + sffunction **f; + sfarg *arg, *argcnt; + char *ech; + char *ch1, *ch2; + char *expcode; /*tokenized form : (f(n)+f(n))*f(n)-n (f-func, n-num,const) */ + unsigned int ui1, ui2; + unsigned char opr; + char err; + sffe *p; +/**************used defines */ +#define MEMERROR 1 +#define UNBALANCEDBRACKES 2 +#define INVALIDFUNCTION 3 +#define INAVLIDNUMBER 4 +#define UNKNOWNCONST 5 +#define OPERATOR 6 +#define STACKERROR 7 +#define PARCNTERROR 8 +#define NO_FUNCTIONS 9 +#define code(chr) \ + expcode = (char*)realloc(expcode,ui1+2);\ + expcode[ui1++] = chr;\ + ch2 = expcode+ui1-1;\ + opr = chr;\ + expcode[ui1] = '\0'; +#define errset(errno) {\ + err = errno;\ + break;} +#define insertfnc(fnc) \ + for ( argcnt=p->args+p->argCount-1; argcnt>arg; argcnt-=1 )\ + argcnt->value = (argcnt-1)->value;\ + sfset(argcnt,-1.0); +#ifdef SFFE_DEVEL +#define sfpopstack(a)\ + {\ + stack->size-=1;\ + insertfnc(NULL);\ + printf("%c",stack->stck[stack->size].c);\ + p->oprs[ui1].arg = (sfarg*)arg;\ + p->oprs[ui1].f = stack->stck[stack->size].f;\ + ui1 += 1;\ + arg += 1;\ + }; +#else +#define sfpopstack(a)\ + {\ + stack->size-=1;\ + insertfnc(NULL);\ + p->oprs[ui1].arg = (sfarg*)arg;\ + p->oprs[ui1].f = stack->stck[stack->size].f;\ + ui1 += 1;\ + arg += 1;\ + }; +#endif + +#define priority(chr)\ + (*chr=='f')?0x60:(\ + (*chr=='^')?0x40:(\ + ((*chr=='/')||(*chr=='*'))?0x20:(\ + ((*chr=='+')||(*chr=='-'))?0x00:0x80\ + )\ + )\ + ) + +#ifdef SFFE_DEVEL + printf("parse - BEGIN\n"); +#endif +/**************** CODE */ + fnctbl = NULL; + ech = expression; + expcode = (char *) malloc(1); + err = 0; + //parser + p = *parser; + /* clear all internal structures */ + if (p->expression) + sffe_clear(parser); + + p->oprCount = 0; + p->argCount = 0; + p->expression = (char *) malloc(strlen(expression) + 1); + strcpy(p->expression, expression); + ech = p->expression; + +#ifdef SFFE_DEVEL + printf + ("\n|-----------------------------------------\n+ > %s[%d] - parsing\n|-----------------------------------------\n", + __FILE__, __LINE__); + printf("| input (dl.=%d) :|%s|\n", strlen(p->expression), + p->expression); +#endif + +/*! PHASE 1 !!!!!!!!! remove spaces, count brackets, change decimal separators ',' to '.', remove multiple operators eg. ++--++1 -> 1, -+++2 -> -2 */ + ch1 = NULL; + ui1 = 0; /*brackets */ + ch2 = ech; + while (isspace(*ech)) + ech += 1; /* skip leading spaces */ + while (*ech) { + /*handle brackets and chaange ','->'.' */ + switch (*ech) { + case '[': + *ech = '('; + case '(': + ui1 += 1; + break; + case ']': + *ech = ')'; + case ')': + ui1 -= 1; + break; + case ',': + *ech = '.'; + break; + }; + *ch2 = (char) toupper((int) *ech); + /*fix multiple arithm operators */ + if (ch1 && strchr("+-/*^", (int) *ech) + && strchr("+-/*^", (int) *ch1)) { + if (*ch1 == '-' && *ech == '-') + *ch1 = '+'; + else if (*ch1 == '-' && *ech == '+') + *ch1 = '-'; + else if (*ch1 == '+' && *ech == '-') + *ch1 = '-'; + else if (*ch1 == *ech) + *ch1 = *ech; + else if (*ech == '-') + ch1 = ++ch2; + else if (*ch1 != *ech) { + err = OPERATOR; + break; + }; + } else { + ch1 = ch2; + ch2 += 1; + }; + do { + ech += 1; + } while (isspace(*ech)); /*skip spaces */ + }; + *ch2 = '\0'; + p->expression = + (char *) realloc(p->expression, strlen(p->expression) + 1); + if (ui1 && !err) + err = UNBALANCEDBRACKES; + +#ifdef SFFE_DEVEL + printf("| check (dl.=%d) :|%s|\n", strlen(p->expression), + p->expression); +#endif + +/*! PHASE 2 !!!!!!!! tokenize expression, lexical analysis (need optimizations) */ + *expcode = '\0'; + ch2 = NULL; + ui1 = 0; + ch1 = NULL; /*string starting position */ + ech = p->expression; + opr = '('; /* in case of leading '-' */ + while (*ech && !err) { + ch1 = ech; + + if (isalpha(*ech)) { + switch (sffe_doname(&ech)) { + case 1: /* const or variable */ + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + arg->value = + (sfNumber *) sffe_variable(p, ch1, + (size_t) (ech - ch1)); + if (!arg->value) { + sfset(arg, 10.0); + if (arg->value) { + if (!sffe_const + (ch1, (size_t) (ech - ch1), arg->value)) + errset(UNKNOWNCONST); + } else + errset(MEMERROR); + }; + opr = 'n'; + break; + case 2: /* function */ + fnctbl = + (sffunction **) realloc(fnctbl, + (p->oprCount + + 1) * sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + f = fnctbl + (p->oprCount++); + *f = NULL; + if (p->userfCount) + /*is it user defined function */ + *f = (sffunction *) (void *) userfunction(p, ch1, + (size_t) (ech + - + ch1)); + if (!*f) + /*if not, is it build in function */ + *f = (sffunction *) (void *) sffe_function(ch1, + (size_t) + (ech - + ch1)); + /* if not -> ERROR */ + if (!*f) + errset(INVALIDFUNCTION); + opr = 'f'; + break; + case 3: /* what ? */ + errset(OPERATOR); + break; + }; + } else /* numbers (this part can be optimized) */ + /* is it a real number */ if (isdigit(*ech) + || (strchr("/*^(", (int) opr) + && strchr("+-", *ech))) { + ch1 = ech; /* st = 1; */ + if (sffe_donum(&ech) > 1) + errset(INAVLIDNUMBER); + /*epx */ + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + /* 22.I.2009 fix for '-n'/'+n', which was parsed as 0*n */ + if ((ech - ch1) == 1 && (*ch1 == '-')) + sfset(arg, -1) + else + sfset(arg, atof(ch1)); + /*epx */ + opr = 'n'; + } else + /* if not, it can be complex number */ +#ifdef SFFE_COMPLEX + if (*ech == '{') { + ech += 1; + p->args = + (sfarg *) realloc(p->args, + (++p->argCount) * sizeof(sfarg)); + if (!p->args) + errset(MEMERROR); + arg = p->args + p->argCount - 1; + sfset(arg, 0); + if (sffe_docmplx(&ech, &arg)) + errset(INAVLIDNUMBER); + opr = 'n'; + } else +#endif + /* if not, we have operator */ + { + ch1 = (char *) sffe_operator(*ech); + + if (ch1) { + fnctbl = + (sffunction **) realloc(fnctbl, + (++p->oprCount) * + sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + fnctbl[p->oprCount - 1] = (sffunction *) ch1; + }; + ch1 = ech; + opr = *ech; + ech += 1; + }; + + + /* check if multiply sign skipped, nf, n(, )( */ + if (!err && ui1 > 0) + if (opr == 'f' || opr == 'n' || opr == '(') + if (*ch2 == 'n' || *ch2 == ')') { + ch1 = (char *) sffe_operator('*'); + fnctbl = + (sffunction **) realloc(fnctbl, + (++p->oprCount) * + sizeof(sffunction *)); + if (!fnctbl) + errset(MEMERROR); + if (opr == 'f') { + fnctbl[p->oprCount - 1] = fnctbl[p->oprCount - 2]; + fnctbl[p->oprCount - 2] = (sffunction *) ch1; + } else + fnctbl[p->oprCount - 1] = (sffunction *) ch1; + ch1 = (char *) (int) opr; /* ]:-> */ + code('*'); + opr = (char) (int) ch1; + ch1 = NULL; + }; + + code(opr); + }; + + ech = expcode; + +#ifdef SFFE_DEVEL + printf + ("| compiled expr. :|%s|\n| operacje: %d\n| stale,zmienne: %d\n| stack not.: ", + expcode, p->oprCount, p->argCount); +#endif + +/*! PRE PHASE 3 !!!!! no operations in expression = single numeric value */ + if (!p->oprCount && p->argCount == 1) { + p->oprs = (sfopr *) malloc(p->argCount * sizeof(sfopr)); + p->oprs[0].arg = (sfarg *) p->args; + p->oprs[0].f = NULL; + p->result = (sfNumber *) p->args->value; + } else +/*! PHASE 3 !!!!! create sffe 'stack' notation ]:-> */ +/* lots of memory operations are done here but no memory leaks should occur */ + if (!err) { + ui1 = p->argCount + p->oprCount; + p->args = (sfarg *) realloc(p->args, ui1 * sizeof(sfarg)); + memset(p->args + p->argCount, 0, p->oprCount * sizeof(sfarg)); + p->argCount = ui1; + arg = p->args; + p->oprs = (sfopr *) malloc(p->oprCount * sizeof(sfopr)); + ch1 = NULL; /* number */ + /* stacks ( stores operations and controls parameters count inside of brackts blocks ) */ + stack = (struct stack__ *) malloc(sizeof(struct stack__)); + stack->size = 0; /* 0-stack is empty, but ready to write (one slot allocated), >0-number of element on stack */ + stack->stck = + (struct opstack__ *) malloc(sizeof(struct opstack__)); + stack->prev = NULL; + memset(stack->stck, 0, sizeof(struct opstack__)); + ui1 = 0; /* used in defines */ + f = fnctbl; + + while (*ech && !err) { + switch (*ech) { + /* O */ + case '+': + case '-': + case '*': + case '/': + case '^': + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + }; + + ch1 = (char *) (int) (priority(ech)); + /* there is an operator on stack */ + if (stack->size) { + /* double casting to get rid of 'cast from pointer to integer of different size' warning + * remove all operators with higher, or equal priority + **/ + while ((unsigned char) (int) ch1 <= + stack->stck[stack->size - 1].t) { + sfpopstack(NULL); + stack->stck = (struct opstack__ *) realloc(stack->stck, sizeof(struct opstack__)); /* is this reallocation really needed ?!? */ + if (stack->size == 0) + break; + }; + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack->size + + 1) * + sizeof(struct + opstack__)); + }; + +#ifdef SFFE_DEVEL + stack->stck[stack->size].c = *ech; +#endif + + stack->stck[stack->size].t = (unsigned char) (int) ch1; /* store operator prority */ + stack->stck[stack->size].f = ((sffunction *) (*f))->fptr; /* get function pointer */ + stack->size += 1; + f += 1; + ch1 = NULL; + break; + /* F */ + case 'f': + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack->size + + 1) * + sizeof(struct opstack__)); +#ifdef SFFE_DEVEL + stack->stck[stack->size].c = 'f'; +#endif + + /* mark operator as a function, and store number of parameters (0 - unlimited) */ + stack->stck[stack->size].t = + 0x60 | (((sffunction *) (*f))->parcnt & 0x1F); + stack->stck[stack->size].f = ((sffunction *) (*f))->fptr; /* get function pointer */ + + stack->size += 1; + f += 1; + ch1 = NULL; + break; + /* ( */ + case '(': + /* store current stack */ + stmp = (struct stack__ *) malloc(sizeof(struct stack__)); + stmp->prev = stack; + stack = stmp; + stack->size = 0; + stack->stck = + (struct opstack__ *) malloc(sizeof(struct opstack__)); +#ifdef SFFE_DEVEL + stack->stck[0].c = '_'; +#endif + opr = 0; + break; + /* ; */ + case ';': + /* check if anything whas been read !!! */ + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + ch1 = NULL; + }; + /* if there is something on stack, flush it we need to read next parameter */ + while (stack->size) + sfpopstack(NULL); + + /* wrong number of parameters */ + ch2 = (char *) (stack->prev->stck + stack->prev->size - 1); + if ((((struct opstack__ *) ch2)->t & 0x1f) == 1) + errset(PARCNTERROR); + ((struct opstack__ *) ch2)->t = + 0x60 | ((((struct opstack__ *) ch2)->t & 0x1f) - 1); + break; + /* ) */ + case ')': + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + } + ch1 = NULL; + + /* if there is something on stack, flush it we need to read next parameter */ + while (stack->size) + sfpopstack(NULL); + + if (!stack->prev) + errset(STACKERROR); + stmp = stack; + free(stmp->stck); + stack = stmp->prev; + free(stmp); + + /* i was reading function, if so at the top of current + * stack is a function. identified by '*.t==3' + **/ + ch2 = (char *) (stack->stck + stack->size - 1); + if ((((struct opstack__ *) ch2)->t & 0xE0) == 0x60) { + /* wrong number of parameters */ + if ((((struct opstack__ *) ch2)->t & 0x1f) > 1) + errset(PARCNTERROR); + if (!err) { + sfpopstack(NULL); + if (stack->size) + stack->stck = + (struct opstack__ *) realloc(stack->stck, + (stack-> + size) * + sizeof(struct + opstack__)); + }; + }; + break; + /* n */ + case 'n': + ch1 = ech; + break; + }; + ech += 1; + }; + + if (!err) { + if (ch1) { +#ifdef SFFE_DEVEL + printf("%c", *ch1); +#endif + arg += 1; + } + + while (stack) { /*clean up stack */ + while (stack->size) { + stack->size -= 1; +#ifdef SFFE_DEVEL + printf("%c", stack->stck[stack->size].c); +#endif + insertfnc(NULL); + p->oprs[ui1].arg = (sfarg *) arg; + p->oprs[ui1].f = stack->stck[stack->size].f; + ui1 += 1; + arg += 1; + }; + free(stack->stck); + stmp = stack->prev; + free(stack); + stack = stmp; + }; + + /* set up formula call stack */ + (p->args)->parg = NULL; + for (ui1 = 1; ui1 < p->argCount; ui1 += 1) + (p->args + ui1)->parg = (p->args + ui1 - 1); + +#ifdef SFFE_DEVEL + printf("\n| numbers :"); + for (ui1 = 0; ui1 < p->argCount; ui1 += 1) { + if ((p->args + ui1)->value) + printf(" %g%+gI", real((*(p->args + ui1)->value)), + imag((*(p->args + ui1)->value))); + else + printf(" [_]"); + }; + + printf("\n| functions fnctbl:"); + for (ui1 = 0; ui1 < p->oprCount; ui1 += 1) + printf(" 0x%.6X [%s]", (int) fnctbl[ui1]->fptr, + fnctbl[ui1]->name); + + printf("\n| functions used ptrs:"); + for (ui1 = 0; ui1 < p->oprCount; ui1 += 1) + printf(" 0x%.6X", (int) p->oprs[ui1].f); +#endif + } else { /* prevent memory leaks */ + + while (stack) { /* clean up stack */ + free(stack->stck); + stmp = stack->prev; + free(stack); + stack = stmp; + }; + }; + /* set up evaluation result pointer (result is stored in last operation return) */ + p->result = (sfNumber *) (p->oprs + p->oprCount - 1)->arg->value; + if (!p->result) + err = MEMERROR; + }; + + if (err) { +#ifdef SFFE_DEVEL + /* in debug mode report errors on stdout */ + printf("Parser error : "); + switch (err) { + case MEMERROR: + printf(" MEMORY ERROR!!"); + break; + case UNBALANCEDBRACKES: + printf(" UNBALANCED BRACKETS!! : %s\n", ch1); + break; + case INVALIDFUNCTION: + printf(" UNKNOWN FUNCTION!! : %s\n", ch1); + break; + case INAVLIDNUMBER: + printf(" NUMBER FORMAT!! : %s\n", ch1); + break; + case UNKNOWNCONST: + printf(" UNKOWN CONST or VAR NAME!! : %s\n", ch1); + break; + case OPERATOR: + printf(" UNKNOWN OPERATOR!! : %s\n", ch1); + break; + case STACKERROR: + printf(" INTERNAL STACK CORRUPTED!! : %s\n", ch1); + break; + case PARCNTERROR: + printf(" FUNCTION PARAMETERS ERROR!! : %s\n", ch1); + break; + case NO_FUNCTIONS: + printf("Formula error ! ARE YOU KIDDING ME ?!? : %s", ch1); + break; + }; +#endif + /* try to store error message */ + if (p->errormsg) + switch (err) { + case MEMERROR: + sprintf(p->errormsg, "Formula error ! MEMORY ERROR!!"); + break; + case UNBALANCEDBRACKES: + sprintf(p->errormsg, + "Formula error ! UNBALANCED BRACKETS!! : %s", ch1); + break; + case INVALIDFUNCTION: + sprintf(p->errormsg, + "Formula error ! UNKNOWN FUNCTION!! : %s", ch1); + break; + case INAVLIDNUMBER: + sprintf(p->errormsg, + "Formula error ! NUMBER FORMAT!! : %s", ch1); + break; + case UNKNOWNCONST: + sprintf(p->errormsg, + "Formula error ! UNKOWN CONST or VAR NAME!! : %s", + ch1); + break; + case OPERATOR: + sprintf(p->errormsg, + "Formula error ! UNKNOWN OPERATOR!! : %s", ch1); + break; + case STACKERROR: + sprintf(p->errormsg, + "Formula error ! INTERNAL STACK CORRUPTED!! : %s", + ch1); + break; + case PARCNTERROR: + sprintf(p->errormsg, + "Formula error ! FUNCTION PARAMETERS ERROR!! : %s", + ch1); + break; + case NO_FUNCTIONS: + sprintf(p->errormsg, + "Formula error ! ARE YOU KIDDING ME ?!? : %s", + ch1); + break; + }; + /* if error -> clean up */ + sffe_clear(&p); + }; + + /*undefine defines */ +#undef priority +#undef sfpopstack +#undef insertfnc +#undef code +#undef errset +#undef MEMERROR +#undef UNBALANCEDBRACKES +#undef INVALIDFUNCTION +#undef INAVLIDNUMBER +#undef UNKNOWNCONST +#undef OPERATOR +#undef STACKERROR +#undef PARCNTERROR + free(expcode); + free(fnctbl); + +#ifdef SFFE_DEVEL + printf("\nparse - END\n"); +#endif + return err; +}; + +#undef sfset +#undef sfvar + +#endif diff --git a/src/sffe/sffe.pri b/src/sffe/sffe.pri new file mode 100644 index 0000000..2935585 --- /dev/null +++ b/src/sffe/sffe.pri @@ -0,0 +1,23 @@ +DEFINES += SFFE_USING SFFE_CMPLX_ASM
+
+SOURCES += \
+ $$PWD/sffe.c \
+ $$PWD/sffe_cmplx_asm.c \
+ $$PWD/sffe_cmplx_gsl.c
+
+ASM_SOURCES += \
+ $$PWD/asm/cmplx.asm
+
+nasm.input = ASM_SOURCES
+nasm.output = $$PWD/${QMAKE_FILE_BASE}.o
+
+win32 {
+ nasm.commands = nasm -f coff -o $$PWD/${QMAKE_FILE_BASE}.o ${QMAKE_FILE_NAME}
+} else:macx {
+ nasm.commands = nasm -f macho -o $$PWD/${QMAKE_FILE_BASE}.o ${QMAKE_FILE_NAME}
+} else {
+ nasm.commands = nasm -f elf -o $$PWD/${QMAKE_FILE_BASE}.o ${QMAKE_FILE_NAME}
+}
+
+
+QMAKE_EXTRA_COMPILERS += nasm
diff --git a/src/sffe/sffe_cmplx_asm.c b/src/sffe/sffe_cmplx_asm.c new file mode 100644 index 0000000..88a008d --- /dev/null +++ b/src/sffe/sffe_cmplx_asm.c @@ -0,0 +1,331 @@ +/*///////////////////////////////////////////////////////////////////////////////////// +// project : sFFe ( SegFault (or Segmentation Fault :) ) formula evalutaor ) +// author : Mateusz Malczak ( mateusz@malczak.info ) +// wpage : www.segfaultlabs.com/projects/sffe +/////////////////////////////////////////////////////////////////////////////////////// +// special build for XaoS, for more info visit +// http://www.segfaultlabs.com/projects/sfXaos +/////////////////////////////////////////////////////////////////////////////////////*/ + +#include <config.h> +#ifdef SFFE_CMPLX_ASM + +#include <math.h> +#include "sffe.h" +#include "sffe_cmplx_asm.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + const sffunction sfcmplxfunc[sffnctscount] = { + /* nie uwzgledniaj w wyszukaniu funkcji */ + {sfpow, 2, "^\0"}, {sfadd, 2, "+\0"}, {sfsub, 2, "-\0"}, {sfmul, 2, + "*\0"}, + {sfdiv, 2, "/\0"}, + /* ponizej uwzgledniaj w wyszukaniu funkcji */ + {sfsin, 1, "SIN\0"}, {sfcos, 1, "COS\0"}, {sftan, 1, "TAN\0"}, + {sfcot, 1, "COT\0"}, + {sfasin, 1, "ASIN\0"}, {sfacos, 1, "ACOS\0"}, {sfatan, 1, + "ATAN\0"}, {sfacot, + 1, + "ACOT\0"}, + {sfatan2, 2, "ATAN2\0"}, + {sfsinh, 1, "SINH\0"}, {sfcosh, 1, "COSH\0"}, {sftanh, 1, + "TANH\0"}, {sfcoth, + 1, + "COTH\0"}, + {sfexp, 1, "EXP\0"}, {sflog, 1, "LOG\0"}, {sflog10, 1, "LOG10\0"}, + {sflog2, 1, "LOG2\0"}, + {sflogN, 2, "LOGN\0"}, {sflogCN, 2, "LOGCN\0"}, + /*power functions */ + {sfpow, 2, "POW\0"}, {sfpowi, 2, "POWI\0"}, {sfpowd, 2, "POWD\0"}, + {sfpowdc, 2, "POWDC\0"}, + {sfsqr, 1, "SQR\0"}, {sfsqrt, 1, "SQRT\0"}, {sfrtni, 3, "RTNI"}, + {sfinv, 1, "INV\n"}, + {sfceil, 1, "CEIL\0"}, {sffloor, 1, "FLOOR\0"}, {sfabs, 1, + "ABS\0"}, {sfrabs, + 1, + "RABS\0"}, + {sfre, 1, "RE\0"}, {sfim, 1, "IM\0"}, + {NULL, 1, "RAD\0"}, {NULL, 1, "DEG\0"}, + {NULL, 1, "SIGN\0"}, {NULL, 1, "TRUNC\0"}, {sfrand, 1, "RAND\0"} + }; + + const char sfcnames[sfvarscount][5] = + { "PI\0", "PI_2\0", "PI2\0", "E\0", "I\0", "RND\0" }; + + const cfptr sfcvals[sfvarscount] = + { sfcPI, sfcPI2, sfc2PI, sfcE, sfcI, sfcRND }; + + + cmplx cset(double r, double i) { + cmplx c; + c.r = r; + c.i = i; + return c; + }; + + cmplx cadd(const cmplx c1, const cmplx c2) { + cmplx r; + r.r = c1.r + c2.r; + r.i = c1.i + c2.i; + return r; + }; + + cmplx csub(const cmplx c1, const cmplx c2) { + cmplx r; + r.r = c1.r - c2.r; + r.i = c1.i - c2.i; + return r; + }; + + cmplx cmul(const cmplx c1, const cmplx c2) { + cmplx r; + r.r = c1.r * c2.r - c1.i * c2.i; + r.i = c1.r * c2.i + c1.i * c2.r; + return r; + }; + + cmplx cdiv(const cmplx c1, const cmplx c2) { + double d = (c2.r * c2.r + c2.i * c2.i); + cmplx r; + r.r = (c1.r * c2.r + c1.i * c2.i) / d; + r.i = (-c1.i * c2.r + c1.r * c2.i) / d; + return r; + }; + + sfarg *sfadd(sfarg * const p) { /* + */ + sfvalue(p) = cadd(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfsub(sfarg * const p) { /* - */ + sfvalue(p) = csub(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfmul(sfarg * const p) { /* * */ + sfvalue(p) = cmul(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfdiv(sfarg * const p) { /* / */ + sfvalue(p) = cdiv(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + + sfarg *sfsin(sfarg * const p) { /* sin */ + sfvalue(p) = sffecsin(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcos(sfarg * const p) { /* cos */ + sfvalue(p) = sffeccos(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sftan(sfarg * const p) { /* tan */ + sfvalue(p) = sffectan(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcot(sfarg * const p) { /* ctan */ + sfvalue(p) = sffeccot(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + + sfarg *sfasin(sfarg * const p) { /* asin */ + //sfvalue(p) = asin( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfacos(sfarg * const p) { /* acos */ + //sfvalue(p) = acos( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfatan(sfarg * const p) { /* atan */ +// sfvalue(p) = atan( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfacot(sfarg * const p) { /* actan */ +// sfvalue(p) = 1.0/atan( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfatan2(sfarg * const p) { /* atan2 */ + //sfvalue(p) = atan2( sfvalue( sfaram2(p) ), sfvalue( sfaram1(p) ) ); + return sfaram2(p); + }; + + + sfarg *sfsinh(sfarg * const p) { /* sinh */ + sfvalue(p) = sffecsinh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcosh(sfarg * const p) { /* cosh */ + sfvalue(p) = sffeccosh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sftanh(sfarg * const p) { /* tanh */ + sfvalue(p) = sffectanh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcoth(sfarg * const p) { /* ctanh */ + sfvalue(p) = sffeccoth(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + + sfarg *sfexp(sfarg * const p) { /* exp */ + sfvalue(p) = sffecexp(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog(sfarg * const p) { /* log */ + sfvalue(p) = sffecln(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog2(sfarg * const p) { /* log2 */ + sfvalue(p) = sffeclog2(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog10(sfarg * const p) { /* log2 */ + sfvalue(p) = sffeclog(sfvalue(sfaram1(p)), 10); + return sfaram1(p); + }; + + sfarg *sflogN(sfarg * const p) { /* logN */ + sfvalue(p) = sffeclog(sfvalue(sfaram1(p)), sfvalue(sfaram2(p)).r); + return sfaram2(p); + }; + + sfarg *sflogCN(sfarg * const p) { /* logCN */ + sfvalue(p) = + cdiv(sffecln(sfvalue(sfaram2(p))), + sffecln(sfvalue(sfaram1(p)))); + return sfaram2(p); + }; + + sfarg *sfpow(sfarg * const p) { /* csflx pow */ + sfvalue(p) = sffeccpow(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfpowi(sfarg * const p) { /* int pow */ + sfvalue(p) = + sffecpowi(sfvalue(sfaram2(p)), (int) (sfvalue(sfaram1(p)).r)); + return sfaram2(p); + }; + + sfarg *sfpowd(sfarg * const p) { /* double pow */ + sfvalue(p) = sffecpowd(sfvalue(sfaram2(p)), sfvalue(sfaram1(p)).r); + return sfaram2(p); + }; + + sfarg *sfpowdc(sfarg * const p) { /* double to csflx pow */ + sfvalue(p) = sffecpowc(sfvalue(sfaram2(p)).r, sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfsqr(sfarg * const p) { /* sqr */ + sfvalue(p) = cmul(sfvalue(sfaram1(p)), sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfsqrt(sfarg * const p) { /* sqrt */ + sfvalue(p) = sffecsqrt(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfrtni(sfarg * const p) /* rtni *///cos tu nie tak jak powinno byc ;( + { + sfvalue(p) = + sffecrtni(sfvalue(sfaram3(p)), (int) (sfvalue(sfaram2(p)).r), + (int) (sfvalue(sfaram1(p)).r)); + return sfaram3(p); + }; + + sfarg *sfinv(sfarg * const p) { /* cinv */ + sfvalue(p) = sffecinv(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfceil(sfarg * const p) { /* ceil */ + //sfvalue(p) = ceil( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sffloor(sfarg * const p) { /* floor */ + //sfvalue(p) = floor( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfabs(sfarg * const p) { /* abs - |z| */ + sfvalue(p).r = sffecabs(sfvalue(sfaram1(p))); + sfvalue(p).i = 0; + return sfaram1(p); + }; + + sfarg *sfrabs(sfarg * const p) { /* abs - real numbers */ + sfvalue(p).r = sfvalue(sfaram1(p)).r; + if (sfvalue(p).r < 0) + sfvalue(p).r = -sfvalue(p).r; + sfvalue(p).i = 0; + return sfaram1(p); + }; + + sfarg *sfre(sfarg * const p) { /* RE */ + sfvalue(p).r = sfvalue(sfaram1(p)).r; + sfvalue(p).i = 0; + return sfaram1(p); + }; + + sfarg *sfim(sfarg * const p) { /* IM */ + sfvalue(p).r = sfvalue(sfaram1(p)).i; + sfvalue(p).i = 0; + return sfaram1(p); + }; + + sfarg *sfrand(sfarg * const p) { /* rand */ + sfvalue(p).r = + sfvalue(sfaram1(p)).r * (double) rand() / (double) RAND_MAX; + sfvalue(p).i = 0; + return sfaram1(p); + }; + +//const eval + void sfcPI(sfNumber * cnst) { + *cnst = cset(4 * atan(1), 0); + }; + void sfcPI2(sfNumber * cnst) { + *cnst = cset(2 * atan(1), 0); + }; + void sfc2PI(sfNumber * cnst) { + *cnst = cset(8 * atan(1), 0); + }; + void sfcE(sfNumber * cnst) { + *cnst = cset(exp(1), 0); + }; + void sfcI(sfNumber * cnst) { + *cnst = cset(0, 1); + }; + void sfcRND(sfNumber * cnst) { + *cnst = cset((double) rand() / (double) RAND_MAX, 0); + }; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sffe/sffe_cmplx_gsl.c b/src/sffe/sffe_cmplx_gsl.c new file mode 100644 index 0000000..6006663 --- /dev/null +++ b/src/sffe/sffe_cmplx_gsl.c @@ -0,0 +1,294 @@ +/*///////////////////////////////////////////////////////////////////////////////////// +// project : sFFe ( SegFault (or Segmentation Fault :) ) formula evalutaor ) +// author : Mateusz Malczak ( mateusz@malczak.info ) +// wpage : www.segfaultlabs.com/projects/sffe +/////////////////////////////////////////////////////////////////////////////////////// +// special build for XaoS, for more info visit +// http://www.segfaultlabs.com/projects/sfXaos +/////////////////////////////////////////////////////////////////////////////////////*/ + +#include <config.h> +#ifdef SFFE_CMPLX_GSL + +#include "sffe.h" +#include "sffe_cmplx_gsl.h" +#include <gsl/gsl_complex.h> +#include <gsl/gsl_complex_math.h> +#include <math.h> + +#ifdef __cplusplus +extern "C" { +#endif + + const sffunction sfcmplxfunc[sffnctscount] = { + /* nie uwzgledniaj w wyszukaniu funkcji */ + {sfpow, 2, "^\0"}, {sfadd, 2, "+\0"}, {sfsub, 2, "-\0"}, {sfmul, 2, + "*\0"}, + {sfdiv, 2, "/\0"}, + /* ponizej uwzgledniaj w wyszukaniu funkcji */ + {sfsin, 1, "SIN\0"}, {sfcos, 1, "COS\0"}, {sftan, 1, "TAN\0"}, + {sfcot, 1, "COT\0"}, + {sfasin, 1, "ASIN\0"}, {sfacos, 1, "ACOS\0"}, {sfatan, 1, + "ATAN\0"}, {sfacot, + 1, + "ACOT\0"}, + {sfatan2, 2, "ATAN2\0"}, + {sfsinh, 1, "SINH\0"}, {sfcosh, 1, "COSH\0"}, {sftanh, 1, + "TANH\0"}, {sfcoth, + 1, + "COTH\0"}, + {sfexp, 1, "EXP\0"}, {sflog, 1, "LOG\0"}, {sflog10, 1, "LOG10\0"}, + {sflog2, 1, "LOG2\0"}, + {sflogN, 2, "LOGN\0"}, {sflogN, 2, "LOGCN\0"}, + /*power functions */ + {sfpow, 2, "POW\0"}, {sfpowd, 2, "POWD\0"}, {sfpow, 2, "POWI\0"}, + {sfpow, 2, "POWDC\0"}, + {sfsqr, 1, "SQR\0"}, {sfsqrt, 1, "SQRT\0"}, {sfrtni, 3, "RTNI"}, + {sfinv, 1, "INV\n"}, + {sfceil, 1, "CEIL\0"}, {sffloor, 1, "FLOOR\0"}, {sfabs, 1, + "ABS\0"}, {sfrabs, + 1, + "RABS\0"}, + {sfre, 1, "RE\0"}, {sfim, 1, "IM\0"}, + {NULL, 1, "RAD\0"}, {NULL, 1, "DEG\0"}, + {NULL, 1, "SIGN\0"}, {NULL, 1, "TRUNC\0"}, {sfrand, 1, "RAND\0"} + }; + + const char sfcnames[sfvarscount][5] = + { "PI\0", "PI_2\0", "PI2\0", "E\0", "I\0", "RND\0" }; + + const cfptr sfcvals[sfvarscount] = + { sfcPI, sfcPI2, sfc2PI, sfcE, sfcI, sfcRND }; + + sfarg *sfadd(sfarg * const p) { /* + */ + sfvalue(p) = + gsl_complex_add(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfsub(sfarg * const p) { /* - */ + sfvalue(p) = + gsl_complex_sub(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfmul(sfarg * const p) { /* * */ + sfvalue(p) = + gsl_complex_mul(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfdiv(sfarg * const p) { /* / */ + sfvalue(p) = + gsl_complex_div(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + + sfarg *sfsin(sfarg * const p) { /* sin */ + sfvalue(p) = gsl_complex_sin(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcos(sfarg * const p) { /* cos */ + sfvalue(p) = gsl_complex_cos(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sftan(sfarg * const p) { /* tan */ + sfvalue(p) = gsl_complex_tan(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcot(sfarg * const p) { /* ctan */ + sfvalue(p) = gsl_complex_cot(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + + sfarg *sfasin(sfarg * const p) { /* asin */ + sfvalue(p) = gsl_complex_arcsin(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfacos(sfarg * const p) { /* acos */ + sfvalue(p) = gsl_complex_arccos(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfatan(sfarg * const p) { /* atan */ + sfvalue(p) = gsl_complex_arctan(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfacot(sfarg * const p) { /* actan */ + sfvalue(p) = gsl_complex_arccot(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfatan2(sfarg * const p) { /* atan2 */ + return sfaram2(p); + }; + + sfarg *sfsinh(sfarg * const p) { /* sinh */ + sfvalue(p) = gsl_complex_sinh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcosh(sfarg * const p) { /* cosh */ + sfvalue(p) = gsl_complex_cosh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sftanh(sfarg * const p) { /* tanh */ + sfvalue(p) = gsl_complex_tanh(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfcoth(sfarg * const p) { /* ctanh */ + sfvalue(p) = gsl_complex_coth(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + + sfarg *sfexp(sfarg * const p) { /* exp */ + sfvalue(p) = gsl_complex_exp(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog(sfarg * const p) { /* log */ + sfvalue(p) = gsl_complex_log(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog10(sfarg * const p) { /* log10 */ + sfvalue(p) = gsl_complex_log10(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sflog2(sfarg * const p) { /* log2 */ + sfNumber base; + real(base) = 2; + imag(base) = 0; + sfvalue(p) = gsl_complex_log_b(sfvalue(sfaram1(p)), base); + return sfaram1(p); + }; + + sfarg *sflogN(sfarg * const p) { /* logN */ + sfvalue(p) = + gsl_complex_log_b(sfvalue(sfaram1(p)), sfvalue(sfaram2(p))); + return sfaram2(p); + }; + + + sfarg *sfpow(sfarg * const p) { /* cmplx pow */ + sfvalue(p) = + gsl_complex_pow(sfvalue(sfaram2(p)), sfvalue(sfaram1(p))); + return sfaram2(p); + }; + + sfarg *sfpowd(sfarg * const p) { /* int pow */ + sfvalue(p) = + gsl_complex_pow_real(sfvalue(sfaram2(p)), + GSL_REAL(sfvalue(sfaram1(p)))); + return sfaram2(p); + }; + + sfarg *sfsqr(sfarg * const p) { /* sqr */ + sfvalue(p) = + gsl_complex_pow(sfvalue(sfaram1(p)), sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfsqrt(sfarg * const p) { /* sqrt */ + sfvalue(p) = gsl_complex_sqrt(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfrtni(sfarg * const p) { /* rtni */ + double nrz = + pow(gsl_complex_abs(sfvalue(sfaram3(p))), + 1.0 / (double) (int) real(sfvalue(sfaram2(p)))); + double alfi = + (gsl_complex_arg(sfvalue(sfaram3(p))) + + 8 * atan(1.0) * (double) (int) real(sfvalue(sfaram1(p)))) / + (double) (int) real(sfvalue(sfaram2(p))); + + cmplxset(sfvalue(sfaram3(p)), nrz * cos(alfi), nrz * sin(alfi)); + return sfaram3(p); + }; + + sfarg *sfinv(sfarg * const p) { /* cinv */ + sfvalue(p) = gsl_complex_inverse(sfvalue(sfaram1(p))); + return sfaram1(p); + }; + + sfarg *sfceil(sfarg * const p) { /* ceil */ + //sfvalue(p) = ceil( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sffloor(sfarg * const p) { /* floor */ + //sfvalue(p) = floor( sfvalue( sfaram1(p) ) ); + return sfaram1(p); + }; + + sfarg *sfabs(sfarg * const p) { /* abs - |z| */ + GSL_REAL(sfvalue(p)) = gsl_complex_abs(sfvalue(sfaram1(p))); + GSL_IMAG(sfvalue(p)) = 0.0; + return sfaram1(p); + }; + + sfarg *sfrabs(sfarg * const p) { /* abs - real numbers */ + GSL_REAL(sfvalue(p)) = GSL_REAL(sfvalue(sfaram1(p))); + if (GSL_REAL(sfvalue(p)) < 0) + GSL_REAL(sfvalue(p)) = -GSL_REAL(sfvalue(p)); + GSL_IMAG(sfvalue(p)) = 0; + return sfaram1(p); + }; + + sfarg *sfre(sfarg * const p) { /* RE */ + GSL_REAL(sfvalue(p)) = GSL_REAL(sfvalue(sfaram1(p))); + GSL_IMAG(sfvalue(p)) = 0.0; + return sfaram1(p); + }; + + sfarg *sfim(sfarg * const p) { /* IM */ + GSL_REAL(sfvalue(p)) = GSL_IMAG(sfvalue(sfaram1(p))); + GSL_IMAG(sfvalue(p)) = 0.0; + return sfaram1(p); + }; + + sfarg *sfrand(sfarg * const p) { /* rand */ + GSL_REAL(sfvalue(p)) = + GSL_REAL(sfvalue(sfaram1(p))) * (double) rand() / + (double) RAND_MAX; + GSL_IMAG(sfvalue(p)) = 0; + return sfaram1(p); + }; + +//const eval + void sfcPI(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, 4 * atan(1), 0); + }; + void sfcPI2(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, 2 * atan(1), 0); + }; + void sfc2PI(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, 8 * atan(1), 0); + }; + void sfcE(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, exp(1), 0); + }; + void sfcI(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, 0, 1); + }; + void sfcRND(sfNumber * cnst) { + GSL_SET_COMPLEX(cnst, rand(), 0); + }; + +#ifdef __cplusplus +} +#endif + +#endif |