3 Copyright (C) 2008 Lutz Mueller
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #define _exception exception
59 #define OP_ERRORFUNC 33
64 int _matherr(struct _exception
*e
) {return 1;}
67 CELL
* incDec(CELL
* params
, int type
)
75 if(params
->next
!= nilCell
)
77 getFloat(params
->next
, &adjust
);
78 adjust
= adjust
* type
;
82 cell
= evaluateExpression(params
);
83 if(cell
->type
!= CELL_SYMBOL
)
85 if(cell
->type
== CELL_DYN_SYMBOL
)
86 sPtr
= getDynamicSymbol(cell
);
88 return(errorProcExt(ERR_SYMBOL_EXPECTED
, params
));
91 sPtr
= (SYMBOL
*)cell
->contents
;
93 if(isProtected(sPtr
->flags
))
94 return(errorProcExt2(ERR_SYMBOL_PROTECTED
, stuffSymbol(sPtr
)));
99 getFloat(cell
, &fValue
);
100 deleteList((CELL
*)sPtr
->contents
);
101 fValue
= fValue
+ adjust
;
102 cell
= getCell(CELL_FLOAT
);
104 *(double *)&cell
->aux
= fValue
;
106 *(double *)&cell
->contents
= fValue
;
108 sPtr
->contents
= (UINT
)cell
;
112 getInteger64(cell
, &lValue
);
113 deleteList((CELL
*)sPtr
->contents
);
114 sPtr
->contents
= (UINT
)stuffInteger64(lValue
+ type
);
117 pushResultFlag
= FALSE
;
118 return((CELL
*)sPtr
->contents
);
122 CELL
* p_increment(CELL
* params
) { return(incDec(params
, 1)); }
123 CELL
* p_decrement(CELL
* params
) { return(incDec(params
, -1)); }
126 CELL
* arithmetikOp(CELL
* params
, int op
)
131 params
= getInteger64(params
, &number
);
134 if(params
== nilCell
)
151 while(params
!= nilCell
)
153 params
= getInteger64(params
, &number
);
156 case OP_ADD
: result
+= number
; break;
157 case OP_SUBTRACT
: result
-= number
; break;
158 case OP_MULTIPLY
: result
*= number
; break;
160 if(number
== 0) return(errorProc(ERR_MATH
));
161 result
/= number
; break;
162 case OP_BIT_OR
: result
|= number
; break;
163 case OP_BIT_AND
: result
&= number
; break;
164 case OP_BIT_XOR
: result
^= number
; break;
165 case OP_SHIFTL
: result
<<= number
; break;
166 case OP_SHIFTR
: result
>>= number
; break;
168 if(number
== 0) return(errorProc(ERR_MATH
));
169 result
%= number
; break;
176 params
= getCell(CELL_INT64
);
177 *(INT64
*)¶ms
->aux
= result
;
180 return(stuffInteger(result
));
185 CELL
* p_add(CELL
* params
) { return(arithmetikOp(params
, OP_ADD
)); }
186 CELL
* p_subtract(CELL
* params
) { return(arithmetikOp(params
, OP_SUBTRACT
)); }
187 CELL
* p_multiply(CELL
* params
) { return(arithmetikOp(params
, OP_MULTIPLY
)); }
188 CELL
* p_divide(CELL
* params
) { return(arithmetikOp(params
, OP_DIVIDE
)); }
190 CELL
* p_bitOr(CELL
* params
) { return(arithmetikOp(params
, OP_BIT_OR
)); }
191 CELL
* p_bitAnd(CELL
* params
) { return(arithmetikOp(params
, OP_BIT_AND
)); }
192 CELL
* p_bitXor(CELL
* params
) { return(arithmetikOp(params
, OP_BIT_XOR
)); }
193 CELL
* p_shiftLeft(CELL
* params
) { return(arithmetikOp(params
, OP_SHIFTL
)); }
194 CELL
* p_shiftRight(CELL
* params
) { return(arithmetikOp(params
, OP_SHIFTR
)); }
195 CELL
* p_modulo(CELL
* params
) { return(arithmetikOp(params
, OP_MODULO
)); }
198 CELL
* p_bitNot(CELL
* params
)
201 getInteger64(params
, &number
);
202 return(stuffInteger64(~number
));
206 /* ----------------------- float arithmetik ----------------------------- */
208 CELL
* getFloat(CELL
* params
, double *);
209 CELL
* floatOp(CELL
* params
, int op
);
210 int compareFloats(CELL
* left
, CELL
* right
);
211 int compareInts(CELL
* left
, CELL
* right
);
214 CELL
* p_addFloat(CELL
* params
) { return(floatOp(params
, OP_ADD
)); }
215 CELL
* p_subFloat(CELL
* params
) { return(floatOp(params
, OP_SUBTRACT
)); }
216 CELL
* p_mulFloat(CELL
* params
) { return(floatOp(params
, OP_MULTIPLY
)); }
217 CELL
* p_divFloat(CELL
* params
) { return(floatOp(params
, OP_DIVIDE
)); }
218 CELL
* p_minFloat(CELL
* params
) { return(floatOp(params
, OP_MIN
)); }
219 CELL
* p_maxFloat(CELL
* params
) { return(floatOp(params
, OP_MAX
)); }
220 CELL
* p_powFloat(CELL
* params
) { return(floatOp(params
, OP_POW
)); }
221 CELL
* p_modFloat(CELL
* params
) { return(floatOp(params
, OP_MODULO
)); }
223 CELL
* floatOp(CELL
* params
, int op
)
228 params
= getFloat(params
, &result
);
229 if(params
== nilCell
)
231 if(op
== OP_SUBTRACT
)
233 else if(op
== OP_DIVIDE
)
234 result
= 1.0 / result
;
235 else if(op
== OP_POW
)
236 result
= result
* result
;
238 while(params
!= nilCell
)
240 params
= getFloat(params
, &number
);
250 case OP_ADD
: result
+= number
; break;
251 case OP_SUBTRACT
: result
-= number
; break;
252 case OP_MULTIPLY
: result
*= number
; break;
255 return(errorProc(ERR_MATH
));
258 case OP_MIN
: if(number
< result
) result
= number
; break;
259 case OP_MAX
: if(number
> result
) result
= number
; break;
260 case OP_POW
: result
= pow(result
, number
); break;
263 return(errorProc(ERR_MATH
));
264 result
= fmod(result
, number
);
269 params
= getCell(CELL_FLOAT
);
271 memcpy((void *)¶ms
->aux
, (void *)&result
, sizeof(double));
273 *(double *)¶ms
->contents
= result
;
279 int compareFloats(CELL
* left
, CELL
* right
)
281 double leftFloat
, rightFloat
;
283 leftFloat
= getDirectFloat(left
);
284 rightFloat
= getDirectFloat(right
);
286 if(isnan(leftFloat
) && isnan(rightFloat
)) return(0);
287 if(isnan(leftFloat
) || isnan(rightFloat
)) return(9);
289 if(leftFloat
< rightFloat
) return(-1);
290 if(leftFloat
> rightFloat
) return(1);
295 int compareInts(CELL
* left
, CELL
* right
)
301 if(left
->type
== CELL_LONG
)
302 leftnum
= (int)left
->contents
;
304 leftnum
= *(INT64
*)&left
->aux
;
306 if(right
->type
== CELL_LONG
)
307 rightnum
= (int)right
->contents
;
309 rightnum
= *(INT64
*)&right
->aux
;
311 leftnum
= (UINT
)left
->contents
;
312 rightnum
= (UINT
)right
->contents
;
315 if(leftnum
< rightnum
) return(-1);
316 if(leftnum
> rightnum
) return(1);
322 double getDirectFloat(CELL
* param
)
324 double floatNum
= 0.0;
327 if(param
->type
== CELL_FLOAT
)
328 return(*(double *)¶m
->aux
);
329 else if(param
->type
== CELL_LONG
)
330 floatNum
= (long)param
->contents
;
331 else if(param
->type
== CELL_INT64
)
332 floatNum
= *(INT64
*)¶m
->aux
;
334 if(param
->type
== CELL_FLOAT
)
335 return(*(double *)¶m
->contents
);
336 else if(param
->type
== CELL_LONG
)
337 floatNum
= (long)param
->contents
;
343 /* ----------------------------- float functions ----------------------- */
346 CELL
* functionFloat(CELL
*, int);
348 CELL
* p_sin(CELL
* params
) { return(functionFloat(params
, OP_SIN
)); }
349 CELL
* p_cos(CELL
* params
) { return(functionFloat(params
, OP_COS
)); }
350 CELL
* p_tan(CELL
* params
) { return(functionFloat(params
, OP_TAN
)); }
351 CELL
* p_asin(CELL
* params
) { return(functionFloat(params
, OP_ASIN
)); }
352 CELL
* p_acos(CELL
* params
) { return(functionFloat(params
, OP_ACOS
)); }
353 CELL
* p_atan(CELL
* params
) { return(functionFloat(params
, OP_ATAN
)); }
354 CELL
* p_sinh(CELL
* params
) { return(functionFloat(params
, OP_SINH
)); }
355 CELL
* p_cosh(CELL
* params
) { return(functionFloat(params
, OP_COSH
)); }
356 CELL
* p_tanh(CELL
* params
) { return(functionFloat(params
, OP_TANH
)); }
357 CELL
* p_asinh(CELL
* params
) { return(functionFloat(params
, OP_ASINH
)); }
358 CELL
* p_acosh(CELL
* params
) { return(functionFloat(params
, OP_ACOSH
)); }
359 CELL
* p_atanh(CELL
* params
) { return(functionFloat(params
, OP_ATANH
)); }
360 CELL
* p_sqrt(CELL
* params
) { return(functionFloat(params
, OP_SQRT
)); }
361 CELL
* p_log(CELL
* params
) { return(functionFloat(params
, OP_LOG
)); }
362 CELL
* p_exp(CELL
* params
) { return(functionFloat(params
, OP_EXP
)); }
363 CELL
* p_abs(CELL
* params
) { return(functionFloat(params
, OP_ABS
)); }
364 CELL
* p_ceil(CELL
* params
) { return(functionFloat(params
, OP_CEIL
)); }
365 CELL
* p_floor(CELL
* params
) { return(functionFloat(params
, OP_FLOOR
)); }
366 CELL
* p_erf(CELL
* params
) { return(functionFloat(params
, OP_ERRORFUNC
)); }
367 CELL
* p_sgn(CELL
* params
) { return(functionFloat(params
, OP_SIGNUM
)); }
368 CELL
* p_isnan(CELL
* params
) { return(functionFloat(params
, OP_ISNAN
)); }
370 CELL
* functionFloat(CELL
* params
, int op
)
376 getFloat(params
, &floatN
);
379 return( stuffFloat(&floatN
) );
384 case OP_SIN
: floatN
= sin(floatN
); break;
385 case OP_COS
: floatN
= cos(floatN
); break;
386 case OP_TAN
: floatN
= tan(floatN
); break;
388 case OP_ASIN
: floatN
= asin(floatN
); break;
389 case OP_ACOS
: floatN
= acos(floatN
); break;
390 case OP_ATAN
: floatN
= atan(floatN
); break;
392 case OP_SINH
: floatN
= sinh(floatN
); break;
393 case OP_COSH
: floatN
= cosh(floatN
); break;
394 case OP_TANH
: floatN
= tanh(floatN
); break;
396 case OP_ASINH
: floatN
= asinh(floatN
); break;
397 case OP_ACOSH
: floatN
= acosh(floatN
); break;
398 case OP_ATANH
: floatN
= atanh(floatN
); break;
400 case OP_SQRT
: floatN
= sqrt(floatN
); break;
402 if(params
->next
!= nilCell
)
404 getFloat(params
->next
, &base
);
405 floatN
= log(floatN
) / log(base
);
408 floatN
= log(floatN
);
410 case OP_EXP
: floatN
= exp(floatN
); break;
411 case OP_ABS
: floatN
= (floatN
< 0.0) ? -floatN
: floatN
; break;
412 case OP_CEIL
: floatN
= ceil(floatN
); break;
413 case OP_FLOOR
: floatN
= floor(floatN
); break;
414 case OP_ERRORFUNC
: floatN
= erf(floatN
); break;
416 if(params
->next
== nilCell
)
418 if(floatN
> 0.0) floatN
= 1.0;
419 else if(floatN
< 0.0) floatN
= -1.0;
425 if(floatN
< 0.0) cell
= params
->next
;
428 params
= params
->next
;
429 if(floatN
== 0.0) cell
= params
->next
;
431 params
= params
->next
;
437 return(copyCell(evaluateExpression(cell
)));
439 return (isnan(floatN
) ? trueCell
: nilCell
);
443 cell
= getCell(CELL_FLOAT
);
445 *(double *)&cell
->aux
= floatN
;
447 *(double *)&cell
->contents
= floatN
;
453 CELL
* p_atan2(CELL
* params
)
455 double floatX
, floatY
;
458 params
= getFloat(params
, &floatX
);
459 getFloat(params
, &floatY
);
461 cell
= getCell(CELL_FLOAT
);
463 *(double *)&cell
->aux
= atan2(floatX
, floatY
);
465 *(double *)&cell
->contents
= atan2(floatX
, floatY
);
471 CELL
* p_round(CELL
* params
)
474 double precision
= 1.0;
480 params
= getFloat(params
, &fNum
);
481 if(params
!= nilCell
)
482 getInteger(params
, (UINT
*)&digits
);
486 precision
= pow(10.0, (double)(digits
> 20 ? 20 : digits
));
487 fNum
= precision
* floor(fNum
/precision
+ 0.5);
493 snprintf(fmt
, 15, "%%.%df", (int)((digits
< -16) ? 16 : -digits
));
494 snprintf(result
, 31, fmt
, fNum
);
498 return(stuffFloat(&fNum
));
502 CELL
* p_rand(CELL
* params
)
510 params
= getInteger(params
, (UINT
*)&range
);
514 srandom((unsigned)time(NULL
));
518 rnum
= ((scale
* random())/(MY_RAND_MAX
- 1));
519 if(params
->type
== CELL_NIL
)
520 return(stuffInteger((UINT
)rnum
));
522 getInteger(params
, (UINT
*)&n
);
524 dist
= getCell(CELL_EXPRESSION
);
526 cell
= stuffInteger((UINT
)rnum
);
527 dist
->contents
= (UINT
)cell
;
532 rnum
= ((scale
* random())/(MY_RAND_MAX
- 1));
533 cell
->next
= stuffInteger((UINT
)rnum
);
541 CELL
* p_amb(CELL
* params
)
545 if((len
= listlen(params
)) == 0) return(nilCell
);
547 len
= random() % len
;
549 while(len
--) params
= params
->next
;
551 return(copyCell(evaluateExpression(params
)));
555 CELL
* p_seed(CELL
* params
)
559 getInteger64(params
, &seedNum
);
561 srandom((UINT
)(seedNum
& 0xFFFFFFFF));
563 return(stuffInteger(seedNum
));
567 /* ----------------------- compare ops --------------------------- */
571 #define OP_LESS_EQUAL 3
572 #define OP_GREATER_EQUAL 4
574 #define OP_NOTEQUAL 6
576 CELL
* p_less(CELL
* params
) { return(compareOp(params
, OP_LESS
)); }
577 CELL
* p_greater(CELL
* params
) { return(compareOp(params
, OP_GREATER
)); }
578 CELL
* p_lessEqual(CELL
* params
) { return(compareOp(params
, OP_LESS_EQUAL
)); }
579 CELL
* p_greaterEqual(CELL
* params
) { return(compareOp(params
, OP_GREATER_EQUAL
)); }
580 CELL
* p_equal(CELL
* params
) { return(compareOp(params
, OP_EQUAL
)); }
581 CELL
* p_notEqual(CELL
* params
) { return(compareOp(params
, OP_NOTEQUAL
)); }
583 CELL
* compareOp(CELL
* params
, int op
)
590 left
= evaluateExpression(params
);
594 if((params
= params
->next
) == nilCell
&& cnt
== 0)
596 if(isNumber(left
->type
))
597 right
= stuffInteger64(0);
598 else if(left
->type
== CELL_STRING
)
599 right
= stuffString("");
600 else if(isList(left
->type
))
601 right
= getCell(CELL_EXPRESSION
);
606 right
= evaluateExpression(params
);
608 if((comp
= compareCells(left
, right
)) == 9) return(nilCell
);
612 if(comp
>= 0) return(nilCell
);
615 if(comp
<= 0) return(nilCell
);
618 if(comp
> 0) return(nilCell
);
620 case OP_GREATER_EQUAL
:
621 if(comp
< 0) return(nilCell
);
624 if(comp
!= 0) return(nilCell
);
627 if(comp
== 0) return(nilCell
);
632 if(params
->next
== nilCell
) break;
639 int compareSymbols(CELL
* left
, CELL
* right
)
645 if(left
->type
== CELL_SYMBOL
)
646 leftS
= (SYMBOL
*)left
->contents
;
648 leftS
= getDynamicSymbol(left
);
650 if(right
->type
== CELL_SYMBOL
)
651 rightS
= (SYMBOL
*)right
->contents
;
653 rightS
= getDynamicSymbol(right
);
655 if(leftS
->context
!= rightS
->context
)
657 leftS
= leftS
->context
;
658 rightS
= rightS
->context
;
661 if((comp
= strcmp((char *)leftS
->name
, (char *)rightS
->name
)) == 0) return(0);
662 return (comp
> 0 ? 1 : -1);
666 /* returns equal: 0 less: -1 greater: 1 or 9 if NaN or Inf equal comparison */
667 int compareCells(CELL
* left
, CELL
* right
)
671 if(left
->type
!= right
->type
)
673 if(left
->type
== CELL_FLOAT
&& ((right
->type
& COMPARE_TYPE_MASK
) == CELL_INT
))
674 return(compareFloats(left
, right
));
675 if(((left
->type
& COMPARE_TYPE_MASK
) == CELL_INT
) && right
->type
== CELL_FLOAT
)
676 return(compareFloats(left
, right
));
678 if((left
->type
& COMPARE_TYPE_MASK
) == CELL_INT
&& (right
->type
& COMPARE_TYPE_MASK
) == CELL_INT
)
679 return(compareInts(left
, right
));
681 if(isSymbol(left
->type
) && isSymbol(right
->type
))
682 return(compareSymbols(left
, right
));
686 if(isNil(right
)) return(0);
692 if(isTrue(right
)) return(0);
693 if(isNil(right
)) return(1);
697 comp
= (left
->type
& COMPARE_TYPE_MASK
) - (right
->type
& COMPARE_TYPE_MASK
);
698 if(comp
== 0) return(0);
700 return( comp
> 0 ? 1 : -1);
706 comp
= left
->aux
- right
->aux
;
709 if((comp
= memcmp((char *)left
->contents
,
710 (char *)right
->contents
,
711 left
->aux
)) == 0) return(0);
715 if((comp
= memcmp((char *)left
->contents
,
716 (char *)right
->contents
,
717 right
->aux
- 1)) == 0)
722 if((comp
= memcmp((char *)left
->contents
,
723 (char *)right
->contents
,
724 left
->aux
- 1)) == 0)
728 return (comp
> 0 ? 1 : -1);
731 case CELL_DYN_SYMBOL
:
732 return(compareSymbols(left
, right
));
735 case CELL_EXPRESSION
:
738 return(compareLists((CELL
*)left
->contents
, (CELL
*)right
->contents
));
740 return(compareArrays((CELL
*)left
, (CELL
*)right
));
742 return(compareFloats(left
, right
));
745 if(*(INT64
*)&left
->aux
> *(INT64
*)&right
->aux
) return(1);
746 if(*(INT64
*)&left
->aux
< *(INT64
*)&right
->aux
) return(-1);
751 if((long)left
->contents
> (long)right
->contents
) return(1);
752 if((long)left
->contents
< (long)right
->contents
) return(-1);
759 int compareLists(CELL
* left
, CELL
* right
)
763 while(left
!= nilCell
)
765 if( (result
= compareCells(left
, right
)) != 0)
770 if(right
== nilCell
) return(0);
775 /* ---------------------------- encryption -----------------------------
777 XOR one-pad enryption
782 void encryptPad(char *encrypted
, char *data
, char * key
, size_t dataLen
, size_t keyLen
)
785 for(i
= 0; i
< dataLen
; i
++)
786 *(encrypted
+ i
) = *(data
+ i
) ^ *(key
+ i
% keyLen
);
790 CELL
* p_encrypt(CELL
* params
)
794 char * dataEncrypted
;
796 size_t dataLen
, keyLen
;
798 getStringSize(params
, &data
, &dataLen
, TRUE
);
799 getStringSize(params
->next
, &key
, &keyLen
, TRUE
);
801 if(!keyLen
) return(errorProcExt(ERR_STRING_EXPECTED
, params
->next
));
803 dataEncrypted
= (char *)allocMemory(dataLen
+ 1);
804 *(dataEncrypted
+ dataLen
) = 0;
806 encryptPad(dataEncrypted
, data
, key
, dataLen
, keyLen
);
808 encrypted
= getCell(CELL_STRING
);
809 encrypted
->contents
= (UINT
)dataEncrypted
;
810 encrypted
->aux
= dataLen
+ 1;
817 /* ============================= Fast Fourier Transform ======================== */
819 CELL
* fft(CELL
* params
, int isign
);
820 CELL
* makeListFromFloats(double num1
, double num2
);
821 double getFloatFromCell(CELL
*);
822 void fastFourierTransform(double data
[], unsigned int nn
, int isign
);
824 CELL
* p_fft(CELL
* params
)
826 return fft(params
, 1);
830 CELL
* p_ifft(CELL
* params
)
832 return fft(params
, -1);
835 CELL
* fft(CELL
* params
, int isign
)
841 unsigned int i
, n
, N
;
843 getListHead(params
, &listData
);
845 n
= listlen(listData
);
848 while(N
< n
) N
<<= 1;
850 data
= (double *)allocMemory(N
* 2 * sizeof(double));
852 for(i
= 0; i
< n
*2; i
+=2)
854 if(isNumber(list
->type
))
856 data
[i
] = getFloatFromCell(list
);
857 data
[i
+1] = (double)0.0;
862 if(list
->type
!= CELL_EXPRESSION
)
865 return(errorProcExt(ERR_LIST_OR_NUMBER_EXPECTED
, list
));
868 cell
= (CELL
*)list
->contents
;
869 data
[i
] = getFloatFromCell(cell
);
870 data
[i
+1] = getFloatFromCell(cell
->next
);
875 for(i
= n
* 2; i
< N
* 2; i
++)
878 fastFourierTransform(data
, N
, isign
);
880 list
= listData
= getCell(CELL_EXPRESSION
);
882 for(i
= 0; i
< n
* 2; i
++) data
[i
] = data
[i
]/N
;
884 list
->contents
= (UINT
)makeListFromFloats(data
[0], data
[1]);
885 list
= (CELL
*)list
->contents
;
886 for(i
= 2; i
< N
* 2; i
+= 2)
888 list
->next
= makeListFromFloats(data
[i
], data
[i
+1]);
898 CELL
* makeListFromFloats(double num1
, double num2
)
903 list
= getCell(CELL_EXPRESSION
);
904 list
->contents
= (UINT
)stuffFloat(&num1
);
905 cell
= (CELL
*)list
->contents
;
906 cell
->next
= stuffFloat(&num2
);
911 double getFloatFromCell(CELL
* cell
)
915 if(cell
->type
== CELL_FLOAT
)
916 memcpy((void *)&number
, (void *)&cell
->aux
, sizeof(double));
917 else if(cell
->type
== CELL_LONG
)
918 number
= (int)cell
->contents
;
919 else number
= (double)*(INT64
*)&cell
->aux
;
921 if(cell
->type
== CELL_FLOAT
)
922 number
= *(double *)&cell
->contents
;
924 number
= (long)cell
->contents
;
930 /* Fast Fourier Transform
931 // algorithm modified for zero-offset data[] and double precision from
933 // Numerical Recipes in 'C', 2nd Edition
934 // W.H. Press, S.A. Teukolsky
935 // W.T. Vettering, B.P. Flannery
936 // Cambridge University Press, 1992
939 #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
941 void fastFourierTransform(double data
[], unsigned int nn
, int isign
)
943 unsigned int n
, mmax
, m
, j
, istep
, i
;
944 double wtemp
, wr
, wpr
, wpi
, wi
, theta
;
950 for(i
= 1; i
< n
; i
+= 2)
954 SWAP(data
[j
-1], data
[i
-1]);
955 SWAP(data
[j
], data
[i
]);
958 while(m
>= 2 && j
> m
)
971 theta
= isign
* (6.28318530717959/mmax
);
972 wtemp
= sin(0.5 * theta
);
973 wpr
= -2.0 * wtemp
* wtemp
;
977 for(m
= 1; m
< mmax
; m
+= 2)
979 for(i
= m
; i
<= n
; i
+= istep
)
982 tempr
= wr
* data
[j
-1] - wi
* data
[j
];
983 tempi
= wr
* data
[j
] + wi
* data
[j
-1];
984 data
[j
-1] = data
[i
-1] - tempr
;
985 data
[j
] = data
[i
] - tempi
;
990 wr
= wtemp
* wpr
- wi
* wpi
+ wr
;
991 wi
= wi
* wpr
+ wtemp
* wpi
+ wi
;
998 /* --------------------------- probability distributions ----------------- */
1000 #define DIST_RANDOM 0
1001 #define DIST_NORMAL 1
1003 double getRandom(double offset
, double scale
, int type
)
1008 if(type
== DIST_RANDOM
)
1011 return(scale
* randnum
/MY_RAND_MAX
+ offset
);
1014 if(type
== DIST_NORMAL
)
1017 for(i
= 0; i
< 12; i
++)
1018 randnum
+= random() % 1024;
1019 return(scale
* (randnum
- 6144)/1024 + offset
);
1025 CELL
* randomDist(CELL
* params
, int type
)
1031 double offset
= 0.0;
1035 if(params
->type
!= CELL_NIL
)
1037 params
= getFloat(params
, &offset
);
1038 params
= getFloat(params
, &scale
);
1039 if(params
->type
!= CELL_NIL
)
1040 getInteger(params
, (UINT
*)&n
);
1045 randnum
= getRandom(offset
, scale
, type
);
1046 return(stuffFloat(&randnum
));
1049 dist
= getCell(CELL_EXPRESSION
);
1050 randnum
= getRandom(offset
, scale
, type
);
1051 dist
->contents
= (UINT
)stuffFloat(&randnum
);
1052 cell
= (CELL
*)dist
->contents
;
1053 for(i
= 1; i
< n
; i
++)
1055 randnum
= getRandom(offset
, scale
, type
);
1056 cell
->next
= stuffFloat(&randnum
);
1064 CELL
* p_normal(CELL
* params
)
1066 return(randomDist(params
, DIST_NORMAL
));
1069 CELL
* p_random(CELL
* params
)
1071 return(randomDist(params
, DIST_RANDOM
));
1074 CELL
* p_randomize(CELL
* params
)
1078 size_t length
, i
, j
;
1082 getListHead(params
, &list
);
1084 if((length
= listlen(list
)) <= 1)
1086 cell
= getCell(CELL_EXPRESSION
);
1087 cell
->contents
= (UINT
)copyList(list
);
1091 repetition
= getFlag(params
->next
);
1093 /* build index vector */
1095 vector
= allocMemory(length
* sizeof(UINT
));
1096 for(i
= 0; i
< length
; i
++)
1098 vector
[i
] = copyCell(cell
);
1099 vector
[i
]->next
= (void *)i
;
1103 /* reorganize randomly */
1105 for(i
= 0; i
< (length
- 1); i
++)
1107 j
= random() % length
;
1109 vector
[i
] = vector
[j
];
1113 /* check that new sequence is different */
1116 for(i
= 0; i
< length
; i
++)
1117 if(vector
[i
]->next
!= (void *)i
) break;
1119 if(i
== length
) goto RANDOMIZE
;
1122 /* relink the list */
1123 cell
= list
= getCell(CELL_EXPRESSION
);
1124 cell
->contents
= (UINT
)vector
[0];
1125 cell
= (CELL
*)cell
->contents
;
1126 for(i
= 1; i
< length
; i
++)
1128 cell
->next
= vector
[i
];
1131 cell
->next
= nilCell
;
1137 /* ---------------------------------------------------------------------
1138 probZ - probability of normal z value
1140 Adapted from a polynomial approximation in:
1141 Ibbetson D, Algorithm 209
1142 Collected Algorithms of the CACM 1963 p. 616
1145 This routine has six digit accuracy, so it is only useful for absolute
1146 z values < 6. For z values >= to 6.0, poz() returns 0.0.
1148 propChi2 - popbablitiy of CHI-2 for df degrees of freedom
1151 Hill, I. D. and Pike, M. C. Algorithm 299
1152 Collected Algorithms for the CACM 1967 p. 243
1153 Updated for rounding errors based on remark in
1154 ACM TOMS June 1985, page 185
1156 critChi2 - Compute critical chi-square value for p and df
1157 critZ - Compute critical Z-value from p
1161 double probChi2(double chi2
, int df
);
1162 double critChi2(double p
, int df
);
1163 double probZ(double z
);
1164 double critZ(double p
);
1165 double gammaln(double xx
);
1166 double betai(double a
, double b
, double x
);
1167 double gammap(double a
, double x
);
1168 double betacf(double a
, double b
, double x
);
1169 static double gser(double a
, double x
, double gln
);
1170 double gcf(double a
, double x
, double gln
);
1172 CELL
* p_probabilityZ(CELL
* params
)
1177 getFloat(params
, &z
);
1180 return(stuffFloat((double *)&p
));
1184 double probChi2(double chi2
, int df
)
1186 return(1.0 - gammap(df
/2, chi2
/2));
1189 CELL
* p_probabilityChi2(CELL
* params
)
1195 params
= getFloat(params
, &chi2
);
1196 getFloat(params
, &df
);
1198 q
= probChi2(chi2
, df
);
1200 return(stuffFloat((double *)&q
));
1204 CELL
* p_criticalChi2(CELL
* params
)
1210 params
= getFloat(params
, &p
);
1211 getInteger(params
, (UINT
*)&df
);
1213 chi
= critChi2(p
, df
);
1215 return(stuffFloat((double *)&chi
));
1219 CELL
* p_criticalZ(CELL
* params
)
1224 getFloat(params
, &p
);
1227 return(stuffFloat((double *)&Z
));
1231 #define Z_MAX 6.0 /* Maximum meaningful z value */
1233 double probZ(double z
)
1238 if (z
== 0.0) x
= 0.0;
1241 y
= 0.5 * (z
< 0.0 ? -z
: z
);
1242 if (y
>= (Z_MAX
* 0.5)) x
= 1.0;
1248 x
= ((((((((0.000124818987 * w
1249 - 0.001075204047) * w
+ 0.005198775019) * w
1250 - 0.019198292004) * w
+ 0.059054035642) * w
1251 - 0.151968751364) * w
+ 0.319152932694) * w
1252 - 0.531923007300) * w
+ 0.797884560593) * y
* 2.0;
1256 x
= (((((((((((((-0.000045255659 * y
1257 + 0.000152529290) * y
- 0.000019538132) * y
1258 - 0.000676904986) * y
+ 0.001390604284) * y
1259 - 0.000794620820) * y
- 0.002034254874) * y
1260 + 0.006549791214) * y
- 0.010557625006) * y
1261 + 0.011630447319) * y
- 0.009279453341) * y
1262 + 0.005353579108) * y
- 0.002141268741) * y
1263 + 0.000535310849) * y
+ 0.999936657524;
1267 return z
> 0.0 ? ((x
+ 1.0) * 0.5) : ((1.0 - x
) * 0.5);
1270 #define BIGX 20.0 /* max value to represent exp(x) */
1274 return (x
< -BIGX
) ? 0.0 : exp(x
);
1278 double critChi2(double p
, int df
)
1280 #define CHI_EPSILON 0.000001 /* Accuracy of critchi approximation */
1281 #define CHI_MAX 99999.0 /* Maximum chi-square value */
1282 double minchisq
= 0.0;
1283 double maxchisq
= CHI_MAX
;
1286 if (p
<= 0.0) return maxchisq
;
1287 else if (p
>= 1.0) return 0.0;
1289 chisqval
= df
/ sqrt(p
); /* fair first value */
1290 while ((maxchisq
- minchisq
) > CHI_EPSILON
)
1292 if (gammap(df
/2, chisqval
/2) < p
) minchisq
= chisqval
;
1293 else maxchisq
= chisqval
;
1294 chisqval
= (maxchisq
+ minchisq
) * 0.5;
1300 double critZ(double p
)
1302 #define Z_EPSILON 0.000001 /* Accuracy of critchi approximation */
1304 double maxZ
= Z_MAX
;
1307 if (p
<= 0.0) return maxZ
;
1308 else if (p
>= 1.0) return 0.0;
1310 Zval
= 2.0; /* fair first value */
1311 while ((maxZ
- minZ
) > Z_EPSILON
)
1313 if (probZ(Zval
) < p
) minZ
= Zval
;
1315 Zval
= (maxZ
+ minZ
) * 0.5;
1321 /* ----------------------- betai and gammaln fucntions ----------------------*/
1324 static int paramError
;
1326 CELL
* p_beta(CELL
* params
)
1330 params
= getFloat(params
, &a
);
1331 getFloat(params
, &b
);
1333 beta
= exp(gammaln(a
) + gammaln(b
) - gammaln(a
+b
));
1335 return(stuffFloat(&beta
));
1338 CELL
* p_betai(CELL
* params
)
1340 double a
, b
, x
, result
;
1342 params
= getFloat(params
, &x
);
1343 params
= getFloat(params
, &a
);
1344 getFloat(params
, &b
);
1348 result
= betai(a
,b
,x
);
1353 return(stuffFloat(&result
));
1357 CELL
* p_gammaln(CELL
* params
)
1361 getFloat(params
, &x
);
1365 result
= gammaln(x
);
1370 return(stuffFloat(&result
));
1374 CELL
* p_gammai(CELL
* params
)
1376 double a
, x
, result
;
1378 params
= getFloat(params
, &a
);
1379 getFloat(params
, &x
);
1381 result
= gammap(a
, x
);
1383 return(stuffFloat(&result
));
1387 /* these functions are adapted from:
1388 Numerical Recipes in C
1389 W.H.Press, S.A. Teukolsky, W.T. Vettering, B.P. Flannery
1390 Cambridge University Press (c) 1992
1396 double betai(double a
, double b
, double x
)
1400 if (x
< 0.0 || x
> 1.0)
1406 if (x
== 0.0 || x
== 1.0)
1409 bt
= exp(gammaln(a
+b
)-gammaln(a
)-gammaln(b
)+a
*log(x
)+b
*log(1.0-x
));
1411 if (x
< (a
+1.0)/(a
+b
+2.0))
1412 return (bt
* betacf(a
,b
,x
) / a
);
1414 return (1.0 - bt
* betacf(b
,a
,1.0-x
) / b
);
1418 double betacf(double a
, double b
, double x
)
1420 double qap
,qam
,qab
,em
,tem
,d
;
1421 double bz
,bm
,bp
,bpp
;
1422 double az
,am
,ap
,app
,aold
;
1430 for (m
=1;m
<=ITMAX
;m
++)
1434 d
=em
*(b
-em
)*x
/((qam
+tem
)*(a
+tem
));
1437 d
= -(a
+em
)*(qab
+em
)*x
/((qap
+tem
)*(a
+tem
));
1445 if (fabs(az
-aold
) < (EPS7
* fabs(az
))) return az
;
1448 return(paramError
= 1);
1452 double gammaln(double xx
)
1455 static double cof
[6] = {
1460 0.1208650973866179e-2,
1461 -0.5395239384953e-5};
1466 fatalError(ERR_INVALID_PARAMETER_0
, NULL
, 0);
1470 tmp
-= (x
+0.5)*log(tmp
);
1471 ser
=1.000000000190015;
1473 for (j
=0;j
<=5;j
++) ser
+= cof
[j
]/++y
;
1475 return -tmp
+log(2.5066282746310005*ser
/x
);
1480 #define FPMIN 1.0e-307
1482 /* incomplete Gamma function
1485 // gammaq = Q(a,x) = 1.0 - P(a,x)
1487 // prob-chi2 = gammap(df/2, chi2/2)
1488 // of beeing as good as observed (>=)
1490 double gammap(double a
, double x
)
1494 return (x
< a
+ 1) ? gser(a
, x
, gln
) : (1.0 - gcf(a
,x
, gln
));
1498 static double gser(double a
, double x
, double gln
)
1500 double ap
, del
, sum
;
1507 for (n
= 1 ; n
<= ITMAX
; n
++)
1512 if (fabs(del
) < fabs(sum
) * EPS9
)
1513 return sum
* exp(-x
+ a
* log(x
) - gln
);
1516 return sum
* exp(-x
+ a
* log(x
) - gln
);
1520 double gcf(double a
, double x
, double gln
)
1522 double b
, c
, d
, h
, an
, del
;
1530 for (i
= 1 ; i
<= ITMAX
; i
++)
1536 if (fabs(d
) < FPMIN
) d
= FPMIN
;
1539 if (fabs(c
) < FPMIN
) c
= FPMIN
;
1544 if (fabs(del
-1.0) < EPS9
) break;
1547 return exp(-x
+ a
* log(x
) - gln
) * h
;
1551 /* ------------------------------------- Binomial distribution -------------------- */
1553 CELL
* p_binomial(CELL
* params
)
1556 double bico
, p
, binomial
;
1558 params
= getInteger(params
, (UINT
*)&n
);
1559 params
= getInteger(params
, (UINT
*)&k
);
1560 getFloat(params
, &p
);
1562 bico
= exp(gammaln(n
+ 1.0) - gammaln(k
+ 1.0) - gammaln(n
- k
+ 1.0));
1565 binomial
= bico
* pow(p
, (double)k
) * pow(1.0 - p
, (double)(n
- k
));
1567 binomial
= bico
* pow(p
, k
) * pow(1.0 - p
, (n
- k
));
1570 return(stuffFloat(&binomial
));
1573 /* -------------------------------------------------------------------------------- */
1575 CELL
* p_series(CELL
* params
)
1577 double fromFlt
, factFlt
, current
;
1583 params
= getFloat(params
, &fromFlt
);
1584 params
= getFloat(params
, &factFlt
);
1585 if(isnan(fromFlt
) || isnan(factFlt
))
1586 return(errorProc(ERR_INVALID_PARAMETER_NAN
));
1587 getInteger(params
, (UINT
*)&count
);
1588 sequence
= getCell(CELL_EXPRESSION
);
1591 cell
= stuffFloat(&fromFlt
);
1592 sequence
->contents
= (UINT
)cell
;
1594 for(i
= 1; i
< count
; i
++)
1597 cell
->next
= stuffFloat(¤t
);
1605 /* ------------------------------- prime numbers ---------------------------- */
1608 * adapted for newLISP from the following code:
1610 * factor.c -- print prime factorization of a number
1611 * Ray Gardner -- 1985 -- public domain
1612 * Modified Feb. 1989 by Thad Smith > public domain
1614 * This version takes numbers up to the limits of double precision.
1618 CELL
* pushFactor (INT64 d
, int k
, INT64
* prevFact
, CELL
* factList
)
1622 factList
->contents
= (UINT
)stuffInteger64(d
);
1623 factList
= (CELL
*)factList
->contents
;
1629 factList
->next
= stuffInteger64(d
);
1630 factList
= factList
->next
;
1639 CELL
* p_factor (CELL
* params
)
1647 getInteger64(params
, &n
);
1649 d
= n
+ 1; /* test for roundoff error */
1651 if ( (n
+ 3 != d
+ 2) || (n
< 2) )
1654 next
= factList
= getCell(CELL_EXPRESSION
);
1659 for ( k
= 0; (n
% d
) == 0; k
++ )
1661 if ( k
) next
= pushFactor(d
, k
, &prevFact
, next
);
1663 for ( d
= 3; d
* d
<= n
; d
+= 2 )
1665 for ( k
= 0; (n
% d
) == 0; k
++ )
1667 if ( k
) next
= pushFactor(d
, k
, &prevFact
, next
);
1674 factList
->contents
= (UINT
)stuffInteger64(n
);
1675 else next
= pushFactor(n
, 1, &prevFact
, next
);
1681 CELL
* p_gcd(CELL
* params
)
1686 params
= getInteger64(params
, &m
);
1690 while(params
!= nilCell
)
1692 params
= getInteger64(params
, &n
);
1696 if (m
< n
) { t
= m
; m
= n
; n
= t
; }
1697 if(n
== 0) {n
= m
; continue; } /* for (gcd x 0) => x */
1699 if (r
== 0) { m
= n
; continue; }
1704 return(stuffInteger64(n
));
1708 /* ------------------------------- financial functions ---------------------- */
1711 CELL
* p_pmt(CELL
* params
)
1719 params
= getFloat(params
, &rate
);
1720 params
= getInteger(params
, (UINT
*)&nper
);
1721 params
= getFloat(params
, &pv
);
1722 if(params
!= nilCell
)
1724 params
= getFloat(params
, &fv
);
1725 getInteger(params
, (UINT
*)&type
);
1731 pmt
= (-pv
- fv
) / nper
;
1734 inc
= pow(1 + rate
, (double)nper
);
1735 pmt
= - (pv
* inc
+ fv
) / ((1 + rate
* type
) * ((inc
- 1) / rate
));
1738 return stuffFloat(&pmt
);
1742 CELL
* p_pv(CELL
* params
)
1745 double rate
, pmt
, pv
;
1749 params
= getFloat(params
, &rate
);
1750 params
= getInteger(params
, (UINT
*)&nper
);
1751 params
= getFloat(params
, &pmt
);
1753 if(params
!= nilCell
)
1755 params
= getFloat(params
, &fv
);
1756 getInteger(params
, (UINT
*)&type
);
1761 pv
= - pmt
* nper
- fv
;
1764 inc
= pow(1 + rate
, (double)nper
);
1765 pv
= (-pmt
* (1 + rate
* type
) * ((inc
- 1) / rate
) - fv
) / inc
;
1768 return stuffFloat(&pv
);
1772 CELL
* p_fv(CELL
* params
)
1774 double rate
, pmt
, pv
;
1778 params
= getFloat(params
, &rate
);
1779 params
= getInteger(params
, (UINT
*)&nper
);
1780 params
= getFloat(params
, &pmt
);
1781 params
= getFloat(params
, &pv
);
1782 if(params
!= nilCell
)
1783 getInteger(params
, (UINT
*)&type
);
1788 fv
= - pmt
* nper
- pv
;
1791 inc
= pow(1 + rate
, (double)nper
);
1792 fv
= -pmt
* (1 + rate
* type
) * ((inc
- 1) / rate
) - pv
* inc
;
1795 return stuffFloat(&fv
);
1799 CELL
* p_nper(CELL
* params
)
1801 double rate
, pmt
, pv
;
1806 params
= getFloat(params
, &rate
);
1807 params
= getFloat(params
, &pmt
);
1808 params
= getFloat(params
, &pv
);
1810 if(params
!= nilCell
)
1812 params
= getFloat(params
, &fv
);
1813 getInteger(params
, (UINT
*)&type
);
1818 nper
= (-pv
- fv
) / pmt
;
1819 else if(rate
> -1.0)
1822 c
= pmt
* (type
? R
: 1.0) / rate
;
1823 nper
= log((c
- fv
) / (c
+ pv
)) / log(R
);
1825 else nper
= sqrt(-1.0); /* NaN */
1828 return stuffFloat(&nper
);
1832 CELL
* p_npv(CELL
* params
)
1835 double rate
, cashFlow
, fNum
;
1838 params
= getFloat(params
, &rate
);
1839 list
= evaluateExpression(params
);
1840 if(!isList(list
->type
))
1841 return(errorProcExt(ERR_LIST_EXPECTED
, params
));
1842 list
= (CELL
*)list
->contents
;
1846 while(list
!= nilCell
)
1849 if(list->type == CELL_FLOAT)
1850 memcpy((void *)&fNum, (void *)&list->aux, sizeof(double));
1851 else if(list->type == CELL_LONG)
1852 fNum = (int)list->contents;
1854 if(isNumber(list
->type
))
1855 fNum
= getFloatFromCell(list
);
1859 cashFlow
+= fNum
/ pow((1.0 + rate
), (double)++count
);
1863 return stuffFloat(&cashFlow
);
1867 /* Internal Rate of Return - irr
1869 adapted from a C++ program by:
1871 Bernt Arne Odegaard, 1999 http://finance.bi.no/~bernt
1873 Note, that some data have multiple solutions, this search
1874 algorithm returns only one
1879 double cfPv(int N
, int times
[], double amounts
[], double rate
)
1884 for(t
= 0; t
< N
; t
++)
1885 PV
+= amounts
[t
] / pow((1.0 + rate
), (double)times
[t
]);
1891 #define PRECISION 1.0e-5
1892 #define MAX_ITERATIONS 50
1893 #define IRR_ERROR -1.0
1895 double irr(int N
, int times
[], double amounts
[], double x2
)
1900 double x_mid
, f_mid
;
1903 est1
= cfPv(N
, times
, amounts
, x1
);
1904 est2
= cfPv(N
, times
, amounts
, x2
);
1906 for(i
=0; i
<MAX_ITERATIONS
; i
++)
1908 if(est1
* est2
< 0.0) break;
1910 if(fabs(est1
) < fabs(est2
))
1911 est1
= cfPv(N
, times
, amounts
, x1
+= 1.6 * (x1
- x2
));
1913 est2
= cfPv(N
, times
, amounts
, x2
+= 1.6 * (x2
- x1
));
1916 if (est2
* est1
> 0.0) return (IRR_ERROR
);
1918 f
= cfPv(N
, times
, amounts
, x1
);
1932 for(i
= 0; i
< MAX_ITERATIONS
; i
++)
1936 f_mid
= cfPv(N
, times
, amounts
, x_mid
);
1941 if((fabs(f_mid
) < PRECISION
) || (fabs(dx
) < PRECISION
))
1948 CELL
* p_irr(CELL
* params
)
1955 double * amountsVec
;
1960 params
= getListHead(params
, &amounts
);
1962 if(params
!= nilCell
)
1964 params
= getListHead(params
, ×
);
1965 if(params
!= nilCell
)
1966 getFloat(params
, &guess
);
1972 while(list
!= nilCell
)
1978 amountsVec
= (double *)allocMemory(N
* sizeof(double));
1979 timesVec
= (int *)allocMemory(N
* sizeof(int));
1981 for(i
= 0; i
< N
; i
++)
1983 if(isNumber(amounts
->type
))
1985 amountsVec
[i
] = getFloatFromCell(amounts
);
1986 amounts
= amounts
->next
;
1992 return(errorProcExt(ERR_NUMBER_EXPECTED
, amounts
));
1996 timesVec
[i
] = i
+ 1;
1999 times
= getIntegerExt(times
, (UINT
*)&number
, FALSE
);
2000 timesVec
[i
] = number
;
2004 result
= irr(N
, timesVec
, amountsVec
, guess
);
2005 if(result
< 0.00001)
2009 result
= floor((10000 * result
+ 0.5))/10000;
2015 if(result
== IRR_ERROR
)
2018 return(stuffFloat(&result
));
2021 /* ----------------------------------- CRC32 ----------------------- */
2023 /* Algorithm from: http://www.w3.org/TR/PNG-CRCAppendix.html */
2025 unsigned int update_crc(unsigned int crc
, unsigned char *buf
, int len
);
2027 CELL
* p_crc32(CELL
* params
)
2032 params
= getStringSize(params
, &data
, &len
, TRUE
);
2033 return(stuffInteger(update_crc(0xffffffffL
, (unsigned char *)data
, (int)len
) ^ 0xffffffffL
));
2036 /* Update a running CRC with the bytes buf[0..len-1]--the CRC
2037 should be initialized to all 1's, and the transmitted value
2038 is the 1's complement of the final running CRC (see the
2039 crc() routine below)).
2042 unsigned int update_crc(unsigned int crc
, unsigned char *buf
, int len
)
2044 unsigned int crc_table
[256];
2048 /* make crc table */
2049 for (n
= 0; n
< 256; n
++)
2051 c
= (unsigned int) n
;
2052 for (k
= 0; k
< 8; k
++)
2055 c
= 0xedb88320L
^ (c
>> 1);
2065 for (n
= 0; n
< len
; n
++)
2066 c
= crc_table
[(c
^ buf
[n
]) & 0xff] ^ (c
>> 8);
2071 /* ----------------------------------- Bayesian statistics -------------------------- */
2075 (bayes-train M1 M2 [M3 ... Mn] D)
2077 takes two or more lists M1, M2 ... with tokens from a joint set of tokens T.
2078 Token can be symbols or strings other datatypes are ignored.
2079 Tokerns are placed in a common dictionary in context D and the frquency
2080 is counted how often they occur in each category Mi.
2082 The M categories represent data models for which a sequence of tokens can be
2083 classified see (bayes-query ...)
2085 Each token in D is a content addressable symbol in D containing a
2086 list of ferquencies of that token how often it occurs in each category.
2087 String tokens are prepended with an undersocre _ before convering them
2090 The function returns a list of token numbers in the different category models:
2091 (N-of-tokens-in-M1 N-of-tokens-in-M2)
2093 (bayes-train M1 M2 [M3 ... Mn] D)
2097 CELL
* p_bayesTrain(CELL
* params
)
2103 int i
, idx
, maxIdx
= 0;
2110 while(list
!= nilCell
) list
= list
->next
, maxIdx
++;
2111 --maxIdx
; /* last is a context not a category */
2112 if(maxIdx
< 1) errorProc(ERR_MISSING_ARGUMENT
);
2114 category
= alloca(maxIdx
* sizeof(CELL
*));
2115 total
= alloca(sizeof(int));
2116 token
= alloca(MAX_STRING
+ 1);
2118 for(idx
= 0; idx
< maxIdx
; idx
++)
2120 params
= getListHead(params
, &list
);
2121 category
[idx
] = list
;
2124 if((ctx
= getCreateContext(params
, TRUE
)) == NULL
)
2125 return(errorProcExt(ERR_SYMBOL_OR_CONTEXT_EXPECTED
, params
));
2127 for(idx
= 0; idx
< maxIdx
; idx
++)
2129 list
= category
[idx
];
2131 while(list
!= nilCell
)
2137 if(list
->aux
> MAX_STRING
) continue;
2139 memcpy(token
+ 1, (char *)list
->contents
, list
->aux
);
2142 strncpy(token
, ((SYMBOL
*)list
->contents
)->name
, MAX_STRING
);
2146 sPtr
= translateCreateSymbol(token
, CELL_EXPRESSION
, ctx
, TRUE
);
2147 if(((CELL
*)sPtr
->contents
)->type
== CELL_NIL
)
2149 /* create list with maxIdx 0s */
2150 count
= getCell(CELL_EXPRESSION
);
2151 sPtr
->contents
= (UINT
)count
;
2152 count
->contents
= (UINT
)stuffInteger(0);
2153 count
= (CELL
*)count
->contents
;
2154 for(i
= 1; i
< maxIdx
; i
++)
2156 count
->next
= stuffInteger(0);
2157 count
= count
->next
;
2161 /* increment value at idx */
2162 count
= (CELL
*)sPtr
->contents
;
2163 if(count
->type
!= CELL_EXPRESSION
)
2164 return(errorProcExt(ERR_LIST_EXPECTED
, count
));
2165 count
= (CELL
*)count
->contents
;
2166 for(i
= 0; i
< idx
; i
++)
2167 count
= count
->next
;
2168 if(count
->type
== CELL_LONG
)
2171 else if(count
->type
== CELL_INT64
)
2172 *(INT64
*)&count
->aux
+= 1;
2175 return(errorProcExt(ERR_NUMBER_EXPECTED
, count
));
2178 } /* done category idx */
2181 totalPtr
= translateCreateSymbol("total", CELL_EXPRESSION
, ctx
, TRUE
);
2182 if(((CELL
*)totalPtr
->contents
)->type
== CELL_NIL
)
2184 count
= getCell(CELL_EXPRESSION
);
2185 totalPtr
->contents
= (UINT
)count
;
2186 count
->contents
= (UINT
)stuffInteger(0);
2187 count
= (CELL
*)count
->contents
;
2188 for(i
= 1; i
< maxIdx
; i
++)
2190 count
->next
= stuffInteger(0);
2191 count
= count
->next
;
2195 count
= (CELL
*)totalPtr
->contents
;
2196 if(count
->type
!= CELL_EXPRESSION
)
2197 return(errorProcExt(ERR_LIST_EXPECTED
, count
));
2198 count
= (CELL
*)count
->contents
;
2199 for(i
= 0; i
< maxIdx
; i
++)
2201 if(count
->type
== CELL_LONG
)
2202 count
->contents
+= total
[i
];
2204 else if(count
->type
== CELL_INT64
)
2205 *(INT64
*)&count
->aux
+= total
[i
];
2207 count
= count
->next
;
2210 return(copyCell((CELL
*)totalPtr
->contents
));
2214 (bayes-query L D [trueChainedBayes])
2215 (bayes-query L D [trueChainedBayes] [trueFloatProbs)
2217 Takes a list of tokens L and a trained dictionary D and returns a list of the
2218 combined probabilities of the tokens to be in one category A versus the other
2219 categories B. All token in L should occur in D, for tokens which are not in D
2220 equal probability is asssumed over categories.
2222 Token can be strings or symbols. If token are strings or symbols they are
2223 prepended with an underscore when looked up in D. When frequencies in D wehere
2224 learned using bayes-train, the underscore was automatically prepended during
2230 p(A|tkn) = ---------------------------------
2231 p(tkn|A) * p(A) + p(tkn|B) * p(B)
2233 p(A|tkn) is the posterior for A which gets prior p(A) for the next token
2234 the priors p(A) and p(B) = p(not A) = 1 are substituted after every token
2239 p(Mc|tkn = ------------------------------- ; Mc is one of N categories
2240 sum-i-N( p(tkn|Mi) * p(Mi) )
2243 When in chain Bayes mode p(Mc|tkn) is the posterior for Mc and replaces
2244 the prior p(Mc) for the next token. In chain Bayes mode tokens with 0 frequency
2245 in one category will effectiviely put the probability of this category to 0.
2246 This causes queries resulting in 0 probabilities for all categories to yield NaN values.
2248 The pure chain Bayes mode is the more sensitive one for changes, when a token count of 0
2249 occurs the resulting probability goes to a complete 0 in this category, while other
2250 categories gain higher probabilities. In the Fisher's Chi2 mode the the zero-category is
2251 still assigned a probability resulting from other tokens with non-zero counts.
2253 Use same or simlar total in training categries when using Fisher Chi2.
2257 CELL
* p_bayesQuery(CELL
* params
)
2268 int nTkn
= 0; /* number of token in query */
2269 int maxIdx
= 0; /* number of catagories */
2270 int N
= 0; /* total of tokens in all categories */
2271 int chainBayes
, probFlag
;
2274 double * p_tkn_and_cat
;
2275 double p_tkn_and_all_cat
;
2276 double * Pchi2
= NULL
;
2277 double * Qchi2
= NULL
;
2279 long countNum
, totalNum
;
2281 CELL
* result
= NULL
;
2284 params
= getListHead(params
, &tokens
);
2285 params
= getContext(params
, &ctx
);
2287 chainBayes
= getFlag(params
);
2288 probFlag
= getFlag(params
->next
);
2290 totPtr
= translateCreateSymbol("total", CELL_EXPRESSION
, ctx
, FALSE
);
2291 if(totPtr
== NULL
) return(nilCell
);
2293 total
= (CELL
*)totPtr
->contents
;
2294 if(total
->type
!= CELL_EXPRESSION
)
2295 return(errorProcExt(ERR_LIST_EXPECTED
, (CELL
*)totPtr
->contents
));
2297 /* get number of categories maxIdx and total N for when
2298 no probabilities are specified but frequencies/counts */
2299 total
= (CELL
*)total
->contents
;
2300 while(total
!= nilCell
)
2302 if(probFlag
== FALSE
)
2304 if(total
->type
== CELL_LONG
)
2305 N
+= total
->contents
;
2307 else if(total
->type
== CELL_INT64
)
2308 N
+= *(INT64
*)&total
->aux
;
2311 total
= total
->next
;
2315 priorP
= alloca(maxIdx
* sizeof(double));
2316 postP
= alloca(maxIdx
* sizeof(double));
2317 p_tkn_and_cat
= alloca(maxIdx
* sizeof(double));
2320 Pchi2
= alloca(maxIdx
* sizeof(double));
2321 Qchi2
= alloca(maxIdx
* sizeof(double));
2324 total
= (CELL
*)((CELL
*)totPtr
->contents
)->contents
;
2325 for(idx
= 0; idx
< maxIdx
; idx
++)
2327 if(probFlag
== TRUE
)
2329 priorP
[idx
] = *(double *)&total
->aux
;
2331 priorP
[idx
] = (double)total
->contents
;
2335 if(total
->type
== CELL_LONG
)
2336 priorP
[idx
] = (double)total
->contents
/ N
;
2339 priorP
[idx
] = (double)*(INT64
*)&total
->aux
/ N
;
2343 /* printf("priorP[%d]=%f\n", idx, priorP[idx]); */
2345 total
= total
->next
;
2346 if(!chainBayes
) Pchi2
[idx
] = Qchi2
[idx
] = 0.0;
2349 token
= alloca(MAX_STRING
+ 1);
2351 while(tkn
!= nilCell
) tkn
= tkn
->next
, nTkn
++;
2354 for(i
= 0; i
< nTkn
; i
++)
2359 if(tkn
->aux
> MAX_STRING
) continue;
2361 memcpy(token
+ 1, (char *)tkn
->contents
, tkn
->aux
);
2364 strncpy(token
, ((SYMBOL
*)tkn
->contents
)->name
, MAX_STRING
);
2368 if((sPtr
= lookupSymbol((char *)token
, ctx
)) == NULL
) continue;
2370 count
= (CELL
*)sPtr
->contents
;
2371 if(count
->type
!= CELL_EXPRESSION
) continue;
2373 count
= (CELL
*)(CELL
*)count
->contents
;
2374 total
= (CELL
*)((CELL
*)totPtr
->contents
)->contents
;
2376 p_tkn_and_all_cat
= 0.0;
2377 for(idx
= 0; idx
< maxIdx
; idx
++)
2381 p_tkn_and_cat
[idx
] = *(double *)&count
->aux
* priorP
[idx
];
2383 p_tkn_and_cat
[idx
] = *(double *)&count
->contents
* priorP
[idx
];
2385 else /* p(M) * p(tkn|M) */
2387 getInteger(count
, (UINT
*)&countNum
);
2388 getInteger(total
, (UINT
*)&totalNum
);
2389 p_tkn_and_cat
[idx
] = priorP
[idx
] * countNum
/ totalNum
;
2392 p_tkn_and_all_cat
+= p_tkn_and_cat
[idx
];
2394 printf("token[%d] p(tkn(M) * p(tkn|M)[%d]=%lf prior[%d]=%lf\n", i, idx,
2395 (double)p_tkn_and_cat[idx], idx, priorP[idx]);
2398 count
= count
->next
;
2399 total
= total
->next
;
2402 for(idx
= 0; idx
< maxIdx
; idx
++)
2406 postP
[idx
] = p_tkn_and_cat
[idx
] / p_tkn_and_all_cat
;
2408 priorP
[idx
] = 1.0 / maxIdx
; /* will cancel out */
2410 if(postP
[idx
] == 0.0)
2411 Qchi2
[idx
] += log(3e-308) * -2.0;
2413 Qchi2
[idx
] += log(postP
[idx
]) * -2.0;
2415 if(postP
[idx
] == 1.0)
2416 Pchi2
[idx
] += log(3e-308) * -2.0;
2418 Pchi2
[idx
] += log(1.0 - postP
[idx
]) * -2.0;
2422 postP
[idx
] = p_tkn_and_cat
[idx
] / p_tkn_and_all_cat
;
2423 priorP
[idx
] = postP
[idx
];
2426 printf("p_tkn_and_cat[%d] / p_tkn_and_all_cat = %lf / %lf = %lf\n",
2427 idx, p_tkn_and_cat[idx], p_tkn_and_all_cat, postP[idx]);
2437 for(idx
= 0; idx
< maxIdx
; idx
++)
2439 postP
[idx
] = (probChi2(Qchi2
[idx
], 2 * nTkn
) - probChi2(Pchi2
[idx
], 2 * nTkn
) + 1.0) / 2.0;
2445 for(idx
= 0; idx
< maxIdx
; idx
++)
2447 /* normalize probs from fisher's Chi2 */
2453 result
= getCell(CELL_EXPRESSION
);
2454 result
->contents
= (UINT
)stuffFloat(postP
+ idx
);
2455 cell
= (CELL
*)result
->contents
;
2459 cell
->next
= stuffFloat(postP
+ idx
);
2469 // Copyright (C) 1992-2007 Lutz Mueller <lutz@nuevatec.com>
2471 // This program is free software; you can redistribute it and/or modify
2472 // it under the terms of the GNU General Public License version 2, 1991,
2473 // as published by the Free Software Foundation.
2475 // This program is distributed in the hope that it will be useful,
2476 // but WITHOUT ANY WARRANTY; without even the implied warranty of
2477 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2478 // GNU General Public License for more details.
2480 // You should have received a copy of the GNU General Public License
2481 // along with this program; if not, write to the Free Software
2482 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2487 'unify' for Prolog like unification of s-expressions:
2488 (unify '(f (g A) A) '(f B xyz)) => binds A to xyz and B to (g xyz)
2490 variable symbols must start with an upper-case letter, variables
2491 containing nil are considered unbound
2493 after linear left to right unification each variable symbol is expanded
2494 by all other variable symbols
2508 void pushSet(TERMSET
* * root
, CELL
* left
, CELL
* right
);
2509 CELL
* unify(CELL
* left
, CELL
* right
);
2510 int unifyGetType(CELL
* cell
);
2511 void substitute(CELL
* expr
, CELL
* sym
, TERMSET
* tset
);
2512 CELL
* subsym(CELL
* expr
, CELL
* sym
, CELL
* cell
);
2513 CELL
* finishUnify(CELL
* result
);
2514 int occurCheck(CELL
* symCell
, CELL
* expr
);
2515 void printStack(TERMSET
* tset
);
2516 void freeTermSet(TERMSET
* * tset
);
2518 TERMSET
* mgu
= NULL
;
2519 TERMSET
* ws
= NULL
;
2527 CELL
* p_unify(CELL
* params
)
2529 CELL
* left
, * right
;
2531 left
= evaluateExpression(params
);
2532 params
= params
->next
;
2533 right
= evaluateExpression(params
);
2534 params
= params
->next
;
2536 if(params
!= nilCell
)
2538 params
= getListHead(params
, &envHead
);
2539 while(envHead
!= nilCell
)
2541 if(envHead
->type
!= CELL_EXPRESSION
)
2542 return(errorProcExt(ERR_LIST_EXPECTED
, envHead
));
2543 pushSet(&ws
, copyCell((CELL
*)envHead
->contents
),
2544 copyCell(((CELL
*)envHead
->contents
)->next
));
2545 envHead
= envHead
->next
;
2549 bindFlag
= getFlag(params
);
2552 debugFlag
= getFlag(params
->next
);
2553 if(debugFlag
) printStack(ws
);
2556 return(unify(left
, right
));
2559 #define UNIFY_ATOM 0
2560 #define UNIFY_LIST 1
2563 void pushSet(TERMSET
* * root
, CELL
* left
, CELL
* right
)
2567 set
= (TERMSET
*)callocMemory(sizeof(TERMSET
));
2575 void popSet(TERMSET
* * root
, CELL
* * left
, CELL
* * right
)
2583 *right
= set
->right
;
2589 CELL
* unify(CELL
* left
, CELL
* right
)
2591 int leftType
, rightType
;
2592 CELL
* lCell
, * rCell
;
2594 pushSet(&ws
, copyCell(left
), copyCell(right
));
2598 popSet(&ws
, &left
, &right
);
2604 printCell(left
, FALSE
, OUT_CONSOLE
);
2606 printCell(right
, FALSE
, OUT_CONSOLE
);
2611 leftType
= unifyGetType(left
);
2612 rightType
= unifyGetType(right
);
2614 if( (leftType
== UNIFY_ATOM
&& rightType
== UNIFY_ATOM
) ||
2615 (left
->contents
== right
->contents
))
2617 if(compareCells(left
, right
) == 0)
2627 return(finishUnify(nilCell
));
2631 if(leftType
== UNIFY_VAR
&& !occurCheck(left
, right
))
2633 substitute(right
, left
, mgu
); /* expand(right-expr, left-sym) in mgu set */
2634 substitute(right
, left
, ws
); /* expand(right-expr, left-sym) in ws set */
2639 printf("ws stack\n");
2643 pushSet(&mgu
, left
, right
);
2647 printf("mgu stack\n");
2654 if(rightType
== UNIFY_VAR
&& !occurCheck(right
, left
))
2656 substitute(left
, right
, mgu
); /* expand(left-expr, right-sym) in mgu set */
2657 substitute(left
, right
, ws
); /* expand(left-expr, right-sym) in ws set */
2661 printf("ws stack\n");
2665 pushSet(&mgu
, right
, left
);
2669 printf("mgu stack\n");
2676 if(leftType
== UNIFY_LIST
&& rightType
== UNIFY_LIST
)
2682 printCell(left
, FALSE
, OUT_CONSOLE
);
2684 printCell(right
, FALSE
, OUT_CONSOLE
);
2688 if(listlen((CELL
*)left
->contents
) != listlen((CELL
*)right
->contents
))
2692 return(finishUnify(nilCell
));
2695 lCell
= (CELL
*)left
->contents
;
2696 rCell
= (CELL
*)right
->contents
;
2697 while(lCell
!= nilCell
)
2699 pushSet(&ws
, copyCell(lCell
), copyCell(rCell
));
2700 lCell
= lCell
->next
;
2701 rCell
= rCell
->next
;
2710 return(finishUnify(nilCell
));
2713 return(finishUnify(trueCell
));
2716 int unifyGetType(CELL
* cell
)
2723 if(isSymbol(cell
->type
))
2725 if(cell
->type
== CELL_SYMBOL
)
2726 sPtr
= (SYMBOL
*)cell
->contents
;
2728 sPtr
= getDynamicSymbol(cell
);
2730 #ifndef SUPPORT_UTF8
2731 return((toupper(*sPtr
->name
) == *sPtr
->name
) ? UNIFY_VAR
: UNIFY_ATOM
);
2733 utf8_wchar(sPtr
->name
, &wchar
);
2734 return((towupper(wchar
) == wchar
) ? UNIFY_VAR
: UNIFY_ATOM
);
2737 else if(isList(cell
->type
))
2744 int occurCheck(CELL
* symCell
, CELL
* expr
)
2748 if(!isEnvelope(expr
->type
))
2749 return(symCell
->contents
== expr
->contents
);
2751 cell
= (CELL
*)expr
->contents
;
2753 while(cell
!= nilCell
)
2755 if(symCell
->contents
== cell
->contents
) return(1);
2756 if(isEnvelope(cell
->type
) && occurCheck(symCell
, cell
)) return(1);
2763 void substitute(CELL
* expr
, CELL
* sym
, TERMSET
* tset
)
2770 printf("empty set in substitute %s for ", ((SYMBOL
*)sym
->contents
)->name
);
2771 printCell(expr
, FALSE
, OUT_CONSOLE
);
2783 printf("substitute %s for ", ((SYMBOL
*)sym
->contents
)->name
);
2784 printCell(expr
, FALSE
, OUT_CONSOLE
);
2787 printCell(tset
->left
, FALSE
, OUT_CONSOLE
);
2790 tset
->left
= subsym(expr
, sym
, tset
->left
);
2795 printCell(tset
->left
, FALSE
, OUT_CONSOLE
);
2797 printCell(tset
->right
, FALSE
, OUT_CONSOLE
);
2800 tset
->right
= subsym(expr
, sym
, tset
->right
);
2805 printCell(tset
->right
, FALSE
, OUT_CONSOLE
);
2814 CELL
* subsym(CELL
* expr
, CELL
* sym
, CELL
* cell
)
2819 sPtr
= (SYMBOL
*)sym
->contents
;
2820 sCell
= (CELL
*)sPtr
->contents
;
2821 sPtr
->contents
= (UINT
)expr
;
2823 if(isEnvelope(cell
->type
))
2825 expr
= expand(copyCell(cell
), sPtr
);
2830 if(cell
->contents
== (UINT
)sPtr
)
2832 expr
= copyCell(expr
);
2839 sPtr
->contents
= (UINT
)sCell
;
2843 CELL
* finishUnify(CELL
* result
)
2845 CELL
* left
, * right
;
2847 CELL
* assoc
, * cell
= NULL
;
2850 if(result
== nilCell
)
2857 /* make an association list of all bound variables */
2860 popSet(&mgu
, &left
, &right
);
2864 assoc
= getCell(CELL_EXPRESSION
);
2865 assoc
->contents
= (UINT
)left
;
2869 list
= getCell(CELL_EXPRESSION
);
2870 list
->contents
= (UINT
)assoc
;
2878 sPtr
= (SYMBOL
*)left
->contents
;
2879 if(isProtected(sPtr
->flags
))
2880 return(errorProcExt2(ERR_SYMBOL_PROTECTED
, stuffSymbol(sPtr
)));
2881 sPtr
->contents
= (UINT
)right
;
2888 if(!list
|| bindFlag
) return(getCell(CELL_EXPRESSION
));
2893 void freeTermSet(TERMSET
* * tset
)
2897 while(*tset
!= NULL
)
2900 deleteList(set
->left
);
2901 deleteList(set
->right
);
2908 void printStack(TERMSET
* tset
)
2912 printCell(tset
->left
, FALSE
, OUT_CONSOLE
);
2914 printCell(tset
->right
, FALSE
, OUT_CONSOLE
);