YAP 7.1.0
arith1.c
Go to the documentation of this file.
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 * File: arith1.c *
12 * Last rev: *
13 * mods: *
14 * comments: arithmetical expression evaluation *
15 * *
16 *************************************************************************/
17#ifdef SCCS
18static char SccsId[] = "%W% %G%";
19#endif
20
230#include "Yap.h"
231#include "Yatom.h"
232#include "YapHeap.h"
233#include "YapEval.h"
234
235static Term
236float_to_int(Float v USES_REGS)
237{
238#if HAVE_ISNAN
239 if (isnan(v)) {
240 if (isoLanguageFlag())
241 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, MkFloatTerm(v),NULL);
242 else
243 return MkFloatTerm(v);
244 }
245#endif
246#if HAVE_ISINF
247 if (isinf(v)) {
248 if (isoLanguageFlag())
249 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(v), "integer (%f)",v);
250 else
251 return MkFloatTerm(v);
252 }
253#endif
254
255 Int i = (Int)v;
256
257 if (i-v == 0.0) {
258 return MkIntegerTerm(i);
259 } else {
260 return Yap_gmp_float_to_big(v);
261 }
262}
263
264#define RBIG_FL(v) return(float_to_int(v PASS_REGS))
265
266typedef struct init_un_eval {
267 char *OpName;
268 arith1_op f;
270
271/* Some compilers just don't get it */
272
273#ifdef __MINGW32__
274#undef HAVE_ASINH
275#undef HAVE_ACOSH
276#undef HAVE_ATANH
277#undef HAVE_FINITE
278#endif
279
280#if !HAVE_ASINH
281#define asinh(F) (log((F)+sqrt((F)*(F)+1)))
282#endif
283#if !HAVE_ACOSH
284#define acosh(F) (log((F)+sqrt((F)*(F)-1)))
285#endif
286#if !HAVE_ATANH
287#define atanh(F) (log((1+(F))/(1-(F)))/2)
288#endif
289
290
291static inline Float
292get_float(Term t) {
293 if (IsFloatTerm(t)) {
294 return FloatOfTerm(t);
295 }
296 if (IsIntTerm(t)) {
297 return IntOfTerm(t);
298 }
299 if (IsLongIntTerm(t)) {
300 return LongIntOfTerm(t);
301 }
302 if (IsBigIntTerm(t)) {
303 return Yap_gmp_to_float(t);
304 }
305 return 0.0;
306}
307
308/* WIN32 machines do not necessarily have rint. This will do for now */
309#if HAVE_RINT
310#define my_rint(X) rint(X)
311#else
312static
313double my_rint(double x)
314{
315 double y, z;
316 Int n;
317
318 if (x >= 0) {
319 y = x + 0.5;
320 z = floor(y);
321 n = (Int) z;
322 if (y == z && n % 2)
323 return(z-1);
324 } else {
325 y = x - 0.5;
326 z = ceil(y);
327 n = (Int) z;
328 if (y == z && n % 2)
329 return(z+1);
330 }
331 return(z);
332}
333#endif
334
335static Int
336msb(Int inp USES_REGS) /* calculate the most significant bit for an integer */
337{
338 /* the obvious solution: do it by using binary search */
339 Int out = 0;
340
341 if (inp < 0) {
342 Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, MkIntegerTerm(inp),
343 "msb/1 received %d", inp);
344 }
345
346#if HAVE__BUILTIN_FFSLL
347 out = __builtin_ffsll(inp);
348#elif HAVE_FFSLL
349 out = ffsll(inp);
350#else
351 if (inp==0)
352 return 0L;
353#if SIZEOF_INT_P == 8
354 if (inp & ((CELL)0xffffffffLL << 32)) {inp >>= 32; out += 32;}
355#endif
356 if (inp & ((CELL)0xffffL << 16)) {inp >>= 16; out += 16;}
357 if (inp & ((CELL)0xffL << 8)) {inp >>= 8; out += 8;}
358 if (inp & ((CELL)0xfL << 4)) {inp >>= 4; out += 4;}
359 if (inp & ((CELL)0x3L << 2)) {inp >>= 2; out += 2;}
360 if (inp & ((CELL)0x1 << 1)) out++;
361#endif
362 return out;
363}
364
365Int
366Yap_msb(Int inp USES_REGS) /* calculate the most significant bit for an integer */
367{
368 return msb(inp PASS_REGS);
369}
370
371
372static Int
373lsb(Int inp USES_REGS) /* calculate the least significant bit for an integer */
374{
375 /* the obvious solution: do it by using binary search */
376 Int out = 0;
377
378 if (inp < 0) {
379 Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, MkIntegerTerm(inp),
380 "msb/1 received %d", inp);
381 }
382 if (inp==0)
383 return 0L;
384#if SIZEOF_INT_P == 8
385 if (!(inp & (CELL)0xffffffffLL)) {inp >>= 32; out += 32;}
386#endif
387 if (!(inp & (CELL)0xffffL)) {inp >>= 16; out += 16;}
388 if (!(inp & (CELL)0xffL)) {inp >>= 8; out += 8;}
389 if (!(inp & (CELL)0xfL)) {inp >>= 4; out += 4;}
390 if (!(inp & (CELL)0x3L)) {inp >>= 2; out += 2;}
391 if (!(inp & ((CELL)0x1))) out++;
392
393 return out;
394}
395
396static Int
397popcount(Int inp USES_REGS) /* calculate the least significant bit for an integer */
398{
399 /* the obvious solution: do it by using binary search */
400 Int c = 0, j = 0, m = ((CELL)1);
401
402 if (inp < 0) {
403 Yap_ArithError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, MkIntegerTerm(inp),
404 "popcount/1 received %d", inp);
405 }
406 if (inp==0)
407 return 0L;
408 for(j=0,c=0; j<sizeof(inp)*8; j++, m<<=1)
409 { if ( inp&m )
410 c++;
411 }
412
413 return c;
414}
415
416static Term
417eval1(Int fi, Term t USES_REGS) {
418 arith1_op f = fi;
419 switch (f) {
420 case op_uplus:
421 return t;
422 case op_uminus:
423 switch (ETypeOfTerm(t)) {
424 case long_int_e:
425 {
426 Int i = IntegerOfTerm(t);
427
428 if (i == Int_MIN) {
429 return Yap_gmp_neg_int(i);
430 }
431 else
432 RINT(-IntegerOfTerm(t));
433 }
434 case double_e:
435 RFLOAT(-FloatOfTerm(t));
436 case big_int_e:
437 return Yap_gmp_neg_big(t);
438 default:
439 RERROR();
440 }
441 case op_unot:
442 switch (ETypeOfTerm(t)) {
443 case long_int_e:
444 RINT(~IntegerOfTerm(t));
445 case double_e:
446 Yap_ArithError(TYPE_ERROR_INTEGER, t, "\\(%f)", FloatOfTerm(t));
447 case big_int_e:
448 return Yap_gmp_unot_big(t);
449 default:
450 RERROR();
451 }
452 case op_exp:
453 RFLOAT(exp(get_float(t)));
454 case op_log:
455 {
456 Float dbl = get_float(t);
457 if (dbl >= 0) {
458 RFLOAT(log(dbl));
459 } else {
460 Yap_ArithError(EVALUATION_ERROR_UNDEFINED, t, "log(%f)", dbl);
461 }
462 }
463 case op_log10:
464 {
465 Float dbl = get_float(t);
466 if (dbl >= 0) {
467 RFLOAT(log10(dbl));
468 } else {
469 Yap_ArithError(EVALUATION_ERROR_UNDEFINED, t, "log10(%f)", dbl);
470 }
471 }
472 case op_sqrt:
473 {
474 Float dbl = get_float(t), out;
475 out = sqrt(dbl);
476#if HAVE_ISNAN
477 if (isnan(out)) {
478 Yap_ArithError(EVALUATION_ERROR_UNDEFINED, t, "sqrt(%f)", dbl);
479 }
480#endif
481 RFLOAT(out);
482 }
483 case op_sin:
484 {
485 Float dbl = get_float(t), out;
486 out = sin(dbl);
487 RFLOAT(out);
488 }
489 case op_cos:
490 {
491 Float dbl = get_float(t), out;
492 out = cos(dbl);
493 RFLOAT(out);
494 }
495 case op_tan:
496 {
497 Float dbl = get_float(t), out;
498 out = tan(dbl);
499 RFLOAT(out);
500 }
501 case op_sinh:
502 {
503 Float dbl = get_float(t), out;
504 out = sinh(dbl);
505 RFLOAT(out);
506 }
507 case op_cosh:
508 {
509 Float dbl = get_float(t), out;
510 out = cosh(dbl);
511 RFLOAT(out);
512 }
513 case op_tanh:
514 {
515 Float dbl = get_float(t), out;
516 out = tanh(dbl);
517 RFLOAT(out);
518 }
519 case op_asin:
520 {
521 Float dbl, out;
522
523 dbl = get_float(t);
524 out = asin(dbl);
525#if HAVE_ISNAN
526 if (isnan(out)) {
527 Yap_ArithError(EVALUATION_ERROR_UNDEFINED, t, "asin(%f)", dbl);
528 }
529#endif
530 RFLOAT(out);
531 }
532 case op_acos:
533 {
534 Float dbl, out;
535
536 dbl = get_float(t);
537 out = acos(dbl);
538#if HAVE_ISNAN
539 if (isnan(out)) {
540 Yap_ArithError(EVALUATION_ERROR_UNDEFINED, t, "acos(%f)", dbl);
541 }
542#endif
543 RFLOAT(out);
544 }
545 case op_atan:
546 {
547 Float dbl, out;
548
549 dbl = get_float(t);
550 out = atan(dbl);
551#if HAVE_ISNAN
552 if (isnan(out)) {
553 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "atan(%f)", dbl);
554 }
555#endif
556 RFLOAT(out);
557 }
558 case op_asinh:
559 {
560 Float dbl, out;
561
562 dbl = get_float(t);
563 out = asinh(dbl);
564#if HAVE_ISNAN
565 if (isnan(out)) {
566 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "asinh(%f)", dbl);
567 }
568#endif
569 RFLOAT(out);
570 }
571 case op_acosh:
572 {
573 Float dbl, out;
574
575 dbl = get_float(t);
576 out = acosh(dbl);
577#if HAVE_ISNAN
578 if (isnan(out)) {
579 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "acosh(%f)", dbl);
580 }
581#endif
582 RFLOAT(out);
583 }
584 case op_atanh:
585 {
586 Float dbl, out;
587
588 dbl = get_float(t);
589 out = atanh(dbl);
590#if HAVE_ISNAN
591 if (isnan(out)) {
592 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "atanh(%f)", dbl);
593 }
594#endif
595 RFLOAT(out);
596 }
597 case op_lgamma:
598 {
599#if HAVE_LGAMMA
600 Float dbl;
601
602 dbl = get_float(t);
603 RFLOAT(lgamma(dbl));
604#else
605 RERROR();
606#endif
607 }
608 case op_erf:
609 {
610#if HAVE_ERF
611 Float dbl = get_float(t), out;
612 out = erf(dbl);
613 RFLOAT(out);
614#else
615 RERROR();
616#endif
617 }
618 case op_erfc:
619 {
620#if HAVE_ERF
621 Float dbl = get_float(t), out;
622 out = erfc(dbl);
623 RFLOAT(out);
624#else
625 RERROR();
626#endif
627 }
628 /*
629 floor(x) maximum integer greatest or equal to X
630
631 There are really two built-ins:
632 SICStus converts from int/big/float -> float
633 ISO only converts from float -> int/big
634
635 */
636 case op_floor:
637 {
638 Float dbl;
639
640 switch (ETypeOfTerm(t)) {
641 case long_int_e:
642 return t;
643 case double_e:
644 dbl = FloatOfTerm(t);
645 break;
646 case big_int_e:
647 return Yap_gmp_floor(t);
648 default:
649 RERROR();
650 }
651#if HAVE_ISNAN
652 if (isnan(dbl)) {
653 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "integer(%f)", dbl);
654 }
655#endif
656#if HAVE_ISINF
657 if (isinf(dbl)) {
658 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer(%f)",dbl);
659 }
660#endif
661 RBIG_FL(floor(dbl));
662 }
663 case op_ceiling:
664 {
665 Float dbl;
666 switch (ETypeOfTerm(t)) {
667 case long_int_e:
668 return t;
669 case double_e:
670 dbl = FloatOfTerm(t);
671 break;
672 case big_int_e:
673 return Yap_gmp_ceiling(t);
674 default:
675 RERROR();
676 }
677#if HAVE_ISNAN
678 if (isnan(dbl)) {
679 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "integer(%f)", dbl);
680 }
681#endif
682#if HAVE_ISINF
683 if (isinf(dbl)) {
684 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer\
685(%f)",dbl);
686 }
687#endif
688 RBIG_FL(ceil(dbl));
689 }
690 case op_round:
691 {
692 Float dbl;
693
694 switch (ETypeOfTerm(t)) {
695 case long_int_e:
696 return t;
697 case double_e:
698 dbl = FloatOfTerm(t);
699 break;
700 case big_int_e:
701 return Yap_gmp_round(t);
702 default:
703 RERROR();
704 }
705#if HAVE_ISNAN
706 if (isnan(dbl)) {
707 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "integer(%f)", dbl);
708 }
709#endif
710#if HAVE_ISINF
711 if (isinf(dbl)) {
712 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer\
713(%f)",dbl);
714 }
715#endif
716 RBIG_FL(my_rint(dbl));
717 }
718 case op_truncate:
719 case op_integer:
720 {
721 Float dbl;
722 switch (ETypeOfTerm(t)) {
723 case long_int_e:
724 return t;
725 case double_e:
726 dbl = FloatOfTerm(t);
727#if HAVE_ISNAN
728 if (isnan(dbl)) {
729 if (isoLanguageFlag())
730 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "integer(%f)", dbl);
731 else
732 RBIG_FL(dbl);
733 }
734#endif
735#if HAVE_ISINF
736 if (isinf(dbl)) {
737 if (isoLanguageFlag())
738 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer (%f)",dbl);
739 else
740 RBIG_FL(dbl);
741 }
742#endif
743 break;
744 case big_int_e:
745 return Yap_gmp_trunc(t);
746 default:
747 RERROR();
748 }
749#if HAVE_ISNAN
750 if (isnan(dbl)) {
751 if (isoLanguageFlag())
752 Yap_ArithError(DOMAIN_ERROR_OUT_OF_RANGE, t, "integer(%f)", dbl);
753 else
754 RBIG_FL(dbl);
755 }
756#endif
757#if HAVE_ISINF
758 if (isinf(dbl)) {
759 if (isoLanguageFlag())
760 Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, MkFloatTerm(dbl), "integer (%f)",dbl);
761 else
762 RBIG_FL(dbl);
763 }
764#endif
765 if (dbl < 0.0)
766 RBIG_FL(ceil(dbl));
767 else
768 RBIG_FL(floor(dbl));
769 }
770 case op_float:
771 switch (ETypeOfTerm(t)) {
772 case long_int_e:
773 RFLOAT(IntegerOfTerm(t));
774 case double_e:
775 return t;
776 case big_int_e:
777 RFLOAT(Yap_gmp_to_float(t));
778 default:
779 RERROR();
780 }
781 case op_rational:
782 switch (ETypeOfTerm(t)) {
783 case long_int_e:
784 return t;
785 case double_e:
786 return Yap_gmp_float_to_rational(FloatOfTerm(t));
787 case big_int_e:
788 return t;
789 default:
790 RERROR();
791 }
792 case op_rationalize:
793 switch (ETypeOfTerm(t)) {
794 case long_int_e:
795 return t;
796 case double_e:
797 return Yap_gmp_float_rationalize(FloatOfTerm(t));
798 case big_int_e:
799 return t;
800 default:
801 RERROR();
802 }
803 case op_abs:
804 switch (ETypeOfTerm(t)) {
805 case long_int_e:
806 RINT(labs(IntegerOfTerm(t)));
807 case double_e:
808 RFLOAT(fabs(FloatOfTerm(t)));
809 case big_int_e:
810 return Yap_gmp_abs_big(t);
811 default:
812 RERROR();
813 }
814 case op_msb:
815 switch (ETypeOfTerm(t)) {
816 case long_int_e:
817 RINT(msb(IntegerOfTerm(t) PASS_REGS));
818 case double_e:
819 Yap_ArithError(TYPE_ERROR_INTEGER, t, "msb(%f)", FloatOfTerm(t));
820 case big_int_e:
821 return Yap_gmp_msb(t);
822 default:
823 RERROR();
824 }
825 case op_lsb:
826 switch (ETypeOfTerm(t)) {
827 case long_int_e:
828 RINT(lsb(IntegerOfTerm(t) PASS_REGS));
829 case double_e:
830 Yap_ArithError(TYPE_ERROR_INTEGER, t, "lsb(%f)", FloatOfTerm(t));
831 case big_int_e:
832 return Yap_gmp_lsb(t);
833 default:
834 RERROR();
835 }
836 case op_popcount:
837 switch (ETypeOfTerm(t)) {
838 case long_int_e:
839 RINT(popcount(IntegerOfTerm(t) PASS_REGS));
840 case double_e:
841 Yap_ArithError(TYPE_ERROR_INTEGER, t, "popcount(%f)", FloatOfTerm(t));
842 case big_int_e:
843
844 return Yap_gmp_popcount(t);
845 default:
846 RERROR();
847 }
848 case op_ffracp:
849 switch (ETypeOfTerm(t)) {
850 case long_int_e:
851 if (isoLanguageFlag()) { /* iso */
852 Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is float_fractional_part(%f)", IntegerOfTerm(t));
853 } else {
854 RFLOAT(0.0);
855 }
856 case double_e:
857 {
858 Float dbl;
859 dbl = FloatOfTerm(t);
860 RFLOAT(dbl-ceil(dbl));
861 }
862 break;
863 case big_int_e:
864 return Yap_gmp_float_fractional_part(t);
865 default:
866 RERROR();
867 }
868 case op_fintp:
869 switch (ETypeOfTerm(t)) {
870 case long_int_e:
871 Yap_ArithError(TYPE_ERROR_FLOAT, t, "X is float_integer_part(%f)", IntegerOfTerm(t));
872 case double_e:
873 RFLOAT(rint(FloatOfTerm(t)));
874 break;
875 case big_int_e:
876 return Yap_gmp_float_integer_part(t);
877 default:
878 RERROR();
879 }
880 case op_sign:
881 switch (ETypeOfTerm(t)) {
882 case long_int_e:
883 {
884 Int x = IntegerOfTerm(t);
885
886 RINT((x > 0 ? 1 : (x < 0 ? -1 : 0)));
887 }
888 case double_e:
889 {
890
891 Float dbl = FloatOfTerm(t);
892
893 RINT((dbl > 0.0 ? 1 : (dbl < 0.0 ? -1 : 0)));
894 }
895 case big_int_e:
896 return Yap_gmp_sign(t);
897 default:
898 RERROR();
899 }
900 case op_random1:
901 switch (ETypeOfTerm(t)) {
902 case long_int_e:
903 RINT(Yap_random()*IntegerOfTerm(t));
904 case double_e:
905 Yap_ArithError(TYPE_ERROR_INTEGER, t, "random(%f)", FloatOfTerm(t));
906 case big_int_e:
907 return Yap_gmp_mul_float_big(Yap_random(), t);
908 default:
909 RERROR();
910 }
911 }
913 RERROR();
914}
915
916Term Yap_eval_unary(Int f, Term t)
917{
918 CACHE_REGS
919 return eval1(f,t PASS_REGS);
920}
921
922static InitUnEntry InitUnTab[] = {
923 {"+", op_uplus},
924 {"-", op_uminus},
925 {"\\", op_unot},
926 {"exp", op_exp},
927 {"log", op_log},
928 {"log10", op_log10},
929 {"sqrt", op_sqrt},
930 {"sin", op_sin},
931 {"cos", op_cos},
932 {"tan", op_tan},
933 {"sinh", op_sinh},
934 {"cosh", op_cosh},
935 {"tanh", op_tanh},
936 {"asin", op_asin},
937 {"acos", op_acos},
938 {"atan", op_atan},
939 {"asinh", op_asinh},
940 {"acosh", op_acosh},
941 {"atanh", op_atanh},
942 {"floor", op_floor},
943 {"ceiling", op_ceiling},
944 {"round", op_round},
945 {"truncate", op_truncate},
946 {"integer", op_integer},
947 {"float", op_float},
948 {"abs", op_abs},
949 {"msb", op_msb},
950 {"lsb", op_lsb},
951 {"popcount", op_popcount},
952 {"float_fractional_part", op_ffracp},
953 {"float_integer_part", op_fintp},
954 {"sign", op_sign},
955 {"lgamma", op_lgamma},
956 {"erf",op_erf},
957 {"erfc",op_erfc},
958 {"rational",op_rational},
959 {"rationalize",op_rationalize},
960 {"random", op_random1}
961};
962
963Atom
964Yap_NameOfUnaryOp(int i)
965{
966 return Yap_LookupAtom(InitUnTab[i].OpName);
967}
968
969static Int
970p_unary_is( USES_REGS1 )
971{ /* X is Y */
972 Term t = Deref(ARG2);
973 Term top;
974 yap_error_number err;
975
976 if (IsVarTerm(t)) {
977 Yap_EvalError(INSTANTIATION_ERROR, t, "unbound unary operator");
978 return FALSE;
979 }
980 Yap_ClearExs();
981 top = Yap_Eval(Deref(ARG3));
982 if ((err=Yap_FoundArithError())) {
983 Yap_EvalError(err,ARG3,"X is op(Y): error in Y ");
984 return FALSE;
985 }
986 if (IsIntTerm(t)) {
987 Term tout;
988 Int i;
989
990 i = IntegerOfTerm(t);
991 tout = eval1(i, top PASS_REGS);
992 if ((err=Yap_FoundArithError())) {
993 Functor f = Yap_MkFunctor( Yap_NameOfUnaryOp(i), 1 );
994 Term t = Yap_MkApplTerm( f, 1, &top );
995 Yap_EvalError(err, t ,"error in %s/1 ", RepAtom(NameOfFunctor(f))->StrOfAE);
996 return FALSE;
997 }
998 return Yap_unify_constant(ARG1,tout);
999 } else if (IsAtomTerm(t)) {
1000 Atom name = AtomOfTerm(t);
1001 ExpEntry *p;
1002 Term out;
1003
1004 if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, 1)))) {
1005 Yap_EvalError(TYPE_ERROR_EVALUABLE, takeIndicator(t),
1006 "functor %s/1 for arithmetic expression",
1007 RepAtom(name)->StrOfAE);
1008 return FALSE;
1009 }
1010 out= eval1(p->FOfEE, top PASS_REGS);
1011 if ((err=Yap_FoundArithError())) {
1012 return FALSE;
1013 }
1014 return Yap_unify_constant(ARG1,out);
1015 }
1016 return(FALSE);
1017}
1018
1019static Int
1020p_unary_op_as_integer( USES_REGS1 )
1021{ /* X is Y */
1022 Term t = Deref(ARG1);
1023
1024 if (IsVarTerm(t)) {
1025 Yap_EvalError(INSTANTIATION_ERROR,t, "X is _Y");
1026 return(FALSE);
1027 }
1028 if (IsIntTerm(t)) {
1029 return Yap_unify_constant(ARG2,t);
1030 }
1031 if (IsAtomTerm(t)) {
1032 Atom name = AtomOfTerm(t);
1033 ExpEntry *p;
1034
1035 if (EndOfPAEntr(p = RepExpProp(Yap_GetExpProp(name, 1)))) {
1036 return Yap_unify(ARG1,ARG2);
1037 }
1038 return Yap_unify_constant(ARG2,MkIntTerm(p->FOfEE));
1039 }
1040 return(FALSE);
1041}
1042
1043void
1044Yap_InitUnaryExps(void)
1045{
1046 unsigned int i;
1047 ExpEntry *p;
1048
1049 for (i = 0; i < sizeof(InitUnTab)/sizeof(InitUnEntry); ++i) {
1050 AtomEntry *ae = RepAtom(Yap_LookupAtom(InitUnTab[i].OpName));
1051 if (ae == NULL) {
1052 Yap_EvalError(RESOURCE_ERROR_HEAP,TermNil,"at InitUnaryExps");
1053 return;
1054 }
1055 WRITE_LOCK(ae->ARWLock);
1056 if (Yap_GetExpPropHavingLock(ae, 1)) {
1057 WRITE_UNLOCK(ae->ARWLock);
1058 break;
1059 }
1060 p = (ExpEntry *) Yap_AllocAtomSpace(sizeof(ExpEntry));
1061 p->KindOfPE = ExpProperty;
1062 p->ArityOfEE = 1;
1063 p->ENoOfEE = 1;
1064 p->FOfEE = InitUnTab[i].f;
1065 AddPropToAtom(ae, (PropEntry *)p);
1066 WRITE_UNLOCK(ae->ARWLock);
1067 }
1068 Yap_InitCPred("is", 3, p_unary_is, TestPredFlag | SafePredFlag);
1069 Yap_InitCPred("$unary_op_as_integer", 2, p_unary_op_as_integer, TestPredFlag|SafePredFlag);}
1070
1071/* This routine is called from Restore to make sure we have the same arithmetic operators */
1072int
1073Yap_ReInitUnaryExps(void)
1074{
1075 return TRUE;
1076}
arith1_op
unary operators
Definition: YapEval.h:217
@ op_log
log( X ), natural logarithm of X
Definition: YapEval.h:257
@ op_log10
log10( X ) [ISO]
Definition: YapEval.h:278
@ op_exp
exp( X ), natural exponentiation of X
Definition: YapEval.h:249
@ op_unot
\ X, The bitwise negation of X
Definition: YapEval.h:241
@ op_uminus
- X: the complement of X
Definition: YapEval.h:231
@ op_uplus
+ X: the value of X
Definition: YapEval.h:224
Main definitions.
A matrix.
Definition: matrix.c:68