2 * value - generic value manipulation routines
4 * Copyright (C) 1999-2007 David I. Bell
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 * Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.5 $
21 * @(#) $Id: value.c,v 30.5 2013/08/11 08:41:38 chongo Exp $
22 * @(#) $Source: /usr/local/src/bin/calc/RCS/value.c,v $
24 * Under source code control: 1990/02/15 01:48:25
25 * File existed as early as: before 1990
27 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
32 #include <sys/types.h>
45 #define LINELEN 80 /* length of a typical tty line */
48 * Free a value and set its type to undefined.
51 * vp value to be freed
56 int type
; /* type of value being freed */
60 vp
->v_subtype
= V_NOSUBTYPE
;
90 assocfree(vp
->v_assoc
);
99 randomfree(vp
->v_random
);
102 config_free(vp
->v_config
);
105 hash_free(vp
->v_hash
);
108 blk_free(vp
->v_block
);
111 math_error("Freeing unknown value type");
118 * Set protection status for a value and all of its components
121 protecttodepth(VALUE
*vp
, int sts
, int depth
)
128 if (vp
->v_type
== V_NBLOCK
) {
130 vp
->v_nblock
->subtype
|= sts
;
132 vp
->v_nblock
->subtype
&= ~(-sts
);
133 else vp
->v_nblock
->subtype
= 0;
137 vp
->v_subtype
|= sts
;
139 vp
->v_subtype
&= ~(-sts
);
147 vq
= vp
->v_mat
->m_table
;
148 i
= vp
->v_mat
->m_size
;
150 protecttodepth(vq
++, sts
, depth
- 1);
153 for (ep
= vp
->v_list
->l_first
; ep
; ep
= ep
->e_next
)
154 protecttodepth(&ep
->e_value
, sts
, depth
- 1);
157 vq
= vp
->v_obj
->o_table
;
158 i
= vp
->v_obj
->o_actions
->oa_count
;
160 protecttodepth(vq
++, sts
, depth
- 1);
164 for (i
= 0; i
< ap
->a_count
; i
++)
165 protecttodepth(assocfindex(ap
, i
), sts
, depth
- 1);
172 * Copy a value from one location to another.
173 * This overwrites the specified new value without checking it.
176 * oldvp value to be copied from
177 * newvp value to be copied into
180 copyvalue(VALUE
*oldvp
, VALUE
*newvp
)
186 newvp
->v_type
= oldvp
->v_type
;
187 if (oldvp
->v_type
>= 0) {
188 switch (oldvp
->v_type
) {
198 newvp
->v_file
= oldvp
->v_file
;
201 newvp
->v_num
= qlink(oldvp
->v_num
);
204 newvp
->v_com
= clink(oldvp
->v_com
);
207 newvp
->v_str
= slink(oldvp
->v_str
);
210 newvp
->v_mat
= matcopy(oldvp
->v_mat
);
213 newvp
->v_list
= listcopy(oldvp
->v_list
);
216 newvp
->v_assoc
= assoccopy(oldvp
->v_assoc
);
219 newvp
->v_obj
= objcopy(oldvp
->v_obj
);
222 newvp
->v_rand
= randcopy(oldvp
->v_rand
);
225 newvp
->v_random
= randomcopy(oldvp
->v_random
);
228 newvp
->v_config
= config_copy(oldvp
->v_config
);
231 newvp
->v_hash
= hash_copy(oldvp
->v_hash
);
234 newvp
->v_block
= blk_copy(oldvp
->v_block
);
237 newvp
->v_type
= V_NUM
;
238 newvp
->v_num
= itoq((long) *oldvp
->v_octet
);
241 newvp
->v_nblock
= oldvp
->v_nblock
;
244 math_error("Copying unknown value type");
248 newvp
->v_subtype
= oldvp
->v_subtype
;
253 * copy the low order 8 bits of a value to an octet
256 copy2octet(VALUE
*vp
, OCTET
*op
)
258 USB8 oval
; /* low order 8 bits to store into OCTET */
262 if (vp
->v_type
== V_ADDR
)
268 * we can (at the moment) only store certain types
269 * values into an OCTET, so get the low order 8 bits
270 * of these particular value types
275 /* nothing to store ... so do nothing */
278 oval
= (USB8
)(vp
->v_int
& 0xff);
281 if (qisint(vp
->v_num
)) {
282 /* use low order 8 bits of integer value */
283 h
= vp
->v_num
->num
.v
[0];
285 /* use low order 8 bits of int(value) */
290 if (qisneg(vp
->v_num
))
295 if (cisint(vp
->v_com
)) {
296 /* use low order 8 bits of integer value */
297 h
= vp
->v_com
->real
->num
.v
[0];
299 /* use low order 8 bits of int(value) */
300 q
= qint(vp
->v_com
->real
);
304 if (qisneg(vp
->v_com
->real
))
309 oval
= (USB8
) vp
->v_str
->s_str
[0];
312 oval
= (USB8
) vp
->v_block
->data
[0];
318 if (vp
->v_nblock
->blk
->data
== NULL
)
320 oval
= (USB8
) vp
->v_nblock
->blk
->data
[0];
323 math_error("invalid assignment into an OCTET");
331 * Negate an arbitrary value.
332 * Result is placed in the indicated location.
335 negvalue(VALUE
*vp
, VALUE
*vres
)
337 vres
->v_type
= vp
->v_type
;
338 vres
->v_subtype
= V_NOSUBTYPE
;
339 switch (vp
->v_type
) {
341 vres
->v_num
= qneg(vp
->v_num
);
344 vres
->v_com
= c_neg(vp
->v_com
);
347 vres
->v_mat
= matneg(vp
->v_mat
);
350 vres
->v_str
= stringneg(vp
->v_str
);
351 if (vres
->v_str
== NULL
)
352 *vres
= error_value(E_STRNEG
);
355 vres
->v_type
= V_NUM
;
356 vres
->v_subtype
= V_NOSUBTYPE
;
357 vres
->v_num
= itoq(- (long) *vp
->v_octet
);
361 *vres
= objcall(OBJ_NEG
, vp
, NULL_VALUE
, NULL_VALUE
);
366 *vres
= error_value(E_NEG
);
373 * Add two arbitrary values together.
374 * Result is placed in the indicated location.
377 addvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
384 vres
->v_subtype
= V_NOSUBTYPE
;
385 if (v1
->v_type
== V_LIST
) {
387 addlistitems(v1
->v_list
, &tmp
);
388 addvalue(&tmp
, v2
, vres
);
391 if (v2
->v_type
== V_LIST
) {
393 addlistitems(v2
->v_list
, vres
);
396 if (v1
->v_type
== V_NULL
) {
400 if (v2
->v_type
== V_NULL
) {
404 vres
->v_type
= v1
->v_type
;
405 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
406 case TWOVAL(V_NUM
, V_NUM
):
407 vres
->v_num
= qqadd(v1
->v_num
, v2
->v_num
);
409 case TWOVAL(V_COM
, V_NUM
):
410 vres
->v_com
= c_addq(v1
->v_com
, v2
->v_num
);
412 case TWOVAL(V_NUM
, V_COM
):
413 vres
->v_com
= c_addq(v2
->v_com
, v1
->v_num
);
414 vres
->v_type
= V_COM
;
416 case TWOVAL(V_COM
, V_COM
):
417 vres
->v_com
= c_add(v1
->v_com
, v2
->v_com
);
421 vres
->v_num
= qlink(c
->real
);
422 vres
->v_type
= V_NUM
;
425 case TWOVAL(V_MAT
, V_MAT
):
426 vres
->v_mat
= matadd(v1
->v_mat
, v2
->v_mat
);
428 case TWOVAL(V_STR
, V_STR
):
429 vres
->v_str
= stringadd(v1
->v_str
, v2
->v_str
);
430 if (vres
->v_str
== NULL
)
431 *vres
= error_value(E_STRADD
);
433 case TWOVAL(V_VPTR
, V_NUM
):
436 math_error("Adding non-integer to address");
440 vres
->v_addr
= v1
->v_addr
+ i
;
441 vres
->v_type
= V_VPTR
;
443 case TWOVAL(V_OPTR
, V_NUM
):
446 math_error("Adding non-integer to address");
450 vres
->v_octet
= v1
->v_octet
+ i
;
451 vres
->v_type
= V_OPTR
;
454 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
458 *vres
= error_value(E_ADD
);
460 vres
->v_type
= v2
->v_type
;
463 *vres
= objcall(OBJ_ADD
, v1
, v2
, NULL_VALUE
);
470 * Subtract one arbitrary value from another one.
471 * Result is placed in the indicated location.
474 subvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
480 vres
->v_type
= v1
->v_type
;
481 vres
->v_subtype
= V_NOSUBTYPE
;
482 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
483 case TWOVAL(V_NUM
, V_NUM
):
484 vres
->v_num
= qsub(v1
->v_num
, v2
->v_num
);
486 case TWOVAL(V_COM
, V_NUM
):
487 vres
->v_com
= c_subq(v1
->v_com
, v2
->v_num
);
489 case TWOVAL(V_NUM
, V_COM
):
490 c
= c_subq(v2
->v_com
, v1
->v_num
);
491 vres
->v_type
= V_COM
;
492 vres
->v_com
= c_neg(c
);
495 case TWOVAL(V_COM
, V_COM
):
496 vres
->v_com
= c_sub(v1
->v_com
, v2
->v_com
);
500 vres
->v_num
= qlink(c
->real
);
501 vres
->v_type
= V_NUM
;
504 case TWOVAL(V_MAT
, V_MAT
):
505 vres
->v_mat
= matsub(v1
->v_mat
, v2
->v_mat
);
507 case TWOVAL(V_STR
, V_STR
):
508 vres
->v_str
= stringsub(v1
->v_str
, v2
->v_str
);
509 if (vres
->v_str
== NULL
)
510 *vres
= error_value(E_STRSUB
);
512 case TWOVAL(V_VPTR
, V_NUM
):
515 math_error("Subtracting non-integer from address");
519 vres
->v_addr
= v1
->v_addr
- i
;
520 vres
->v_type
= V_VPTR
;
522 case TWOVAL(V_OPTR
, V_NUM
):
525 math_error("Adding non-integer to address");
529 vres
->v_octet
= v1
->v_octet
- i
;
530 vres
->v_type
= V_OPTR
;
532 case TWOVAL(V_VPTR
, V_VPTR
):
533 vres
->v_type
= V_NUM
;
534 vres
->v_num
= itoq(v1
->v_addr
- v2
->v_addr
);
536 case TWOVAL(V_OPTR
, V_OPTR
):
537 vres
->v_type
= V_NUM
;
538 vres
->v_num
= itoq(v1
->v_octet
- v2
->v_octet
);
541 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
544 if (v2
->v_type
<= 0) {
545 vres
->v_type
= v2
->v_type
;
548 *vres
= error_value(E_SUB
);
551 *vres
= objcall(OBJ_SUB
, v1
, v2
, NULL_VALUE
);
558 * Multiply two arbitrary values together.
559 * Result is placed in the indicated location.
562 mulvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
566 vres
->v_type
= v1
->v_type
;
567 vres
->v_subtype
= V_NOSUBTYPE
;
568 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
569 case TWOVAL(V_NUM
, V_NUM
):
570 vres
->v_num
= qmul(v1
->v_num
, v2
->v_num
);
572 case TWOVAL(V_COM
, V_NUM
):
573 vres
->v_com
= c_mulq(v1
->v_com
, v2
->v_num
);
575 case TWOVAL(V_NUM
, V_COM
):
576 vres
->v_com
= c_mulq(v2
->v_com
, v1
->v_num
);
577 vres
->v_type
= V_COM
;
579 case TWOVAL(V_COM
, V_COM
):
580 vres
->v_com
= c_mul(v1
->v_com
, v2
->v_com
);
582 case TWOVAL(V_MAT
, V_MAT
):
583 vres
->v_mat
= matmul(v1
->v_mat
, v2
->v_mat
);
585 case TWOVAL(V_MAT
, V_NUM
):
586 case TWOVAL(V_MAT
, V_COM
):
587 vres
->v_mat
= matmulval(v1
->v_mat
, v2
);
589 case TWOVAL(V_NUM
, V_MAT
):
590 case TWOVAL(V_COM
, V_MAT
):
591 vres
->v_mat
= matmulval(v2
->v_mat
, v1
);
592 vres
->v_type
= V_MAT
;
594 case TWOVAL(V_NUM
, V_STR
):
595 vres
->v_type
= V_STR
;
596 vres
->v_str
= stringmul(v1
->v_num
, v2
->v_str
);
597 if (vres
->v_str
== NULL
)
598 *vres
= error_value(E_STRMUL
);
600 case TWOVAL(V_STR
, V_NUM
):
601 vres
->v_str
= stringmul(v2
->v_num
, v1
->v_str
);
602 if (vres
->v_str
== NULL
)
603 *vres
= error_value(E_STRMUL
);
606 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
609 if (v2
->v_type
<= 0) {
610 vres
->v_type
= v2
->v_type
;
613 *vres
= error_value(E_MUL
);
616 *vres
= objcall(OBJ_MUL
, v1
, v2
, NULL_VALUE
);
621 vres
->v_num
= qlink(c
->real
);
622 vres
->v_type
= V_NUM
;
629 * Square an arbitrary value.
630 * Result is placed in the indicated location.
633 squarevalue(VALUE
*vp
, VALUE
*vres
)
637 vres
->v_type
= vp
->v_type
;
638 vres
->v_subtype
= V_NOSUBTYPE
;
639 switch (vp
->v_type
) {
641 vres
->v_num
= qsquare(vp
->v_num
);
644 vres
->v_com
= c_square(vp
->v_com
);
648 vres
->v_num
= qlink(c
->real
);
649 vres
->v_type
= V_NUM
;
653 vres
->v_mat
= matsquare(vp
->v_mat
);
656 *vres
= objcall(OBJ_SQUARE
, vp
, NULL_VALUE
, NULL_VALUE
);
659 if (vp
->v_type
<= 0) {
660 vres
->v_type
= vp
->v_type
;
663 *vres
= error_value(E_SQUARE
);
670 * Invert an arbitrary value.
671 * Result is placed in the indicated location.
674 invertvalue(VALUE
*vp
, VALUE
*vres
)
678 vres
->v_type
= vp
->v_type
;
679 vres
->v_subtype
= V_NOSUBTYPE
;
680 switch (vp
->v_type
) {
682 if (qiszero(vp
->v_num
))
683 *vres
= error_value(E_1OVER0
);
685 vres
->v_num
= qinv(vp
->v_num
);
688 vres
->v_com
= c_inv(vp
->v_com
);
691 vres
->v_mat
= matinv(vp
->v_mat
);
694 if (*vp
->v_octet
== 0) {
695 *vres
= error_value(E_1OVER0
);
698 q1
= itoq((long) *vp
->v_octet
);
702 vres
->v_type
= V_NUM
;
705 *vres
= objcall(OBJ_INV
, vp
, NULL_VALUE
, NULL_VALUE
);
708 if (vp
->v_type
== -E_1OVER0
) {
709 vres
->v_type
= V_NUM
;
710 vres
->v_num
= qlink(&_qzero_
);
715 *vres
= error_value(E_INV
);
723 * "AND" two arbitrary values together.
724 * Result is placed in the indicated location.
727 andvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
729 vres
->v_subtype
= V_NOSUBTYPE
;
730 if (v1
->v_type
== V_NULL
) {
734 if (v2
->v_type
== V_NULL
) {
738 vres
->v_type
= v1
->v_type
;
739 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
740 case TWOVAL(V_NUM
, V_NUM
):
741 vres
->v_num
= qand(v1
->v_num
, v2
->v_num
);
743 case TWOVAL(V_STR
, V_STR
):
744 vres
->v_str
= stringand(v1
->v_str
, v2
->v_str
);
745 if (vres
->v_str
== NULL
)
746 *vres
= error_value(E_STRAND
);
748 case TWOVAL(V_OCTET
, V_OCTET
):
749 vres
->v_type
= V_STR
;
750 vres
->v_str
= charstring(*v1
->v_octet
& *v2
->v_octet
);
752 case TWOVAL(V_STR
, V_OCTET
):
753 vres
->v_str
= charstring(*v1
->v_str
->s_str
&
756 case TWOVAL(V_OCTET
, V_STR
):
757 vres
->v_type
= V_STR
;
758 vres
->v_str
= charstring(*v1
->v_octet
&
762 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
765 if (v2
->v_type
< 0) {
766 vres
->v_type
= v2
->v_type
;
769 *vres
= error_value(E_AND
);
772 *vres
= objcall(OBJ_AND
, v1
, v2
, NULL_VALUE
);
779 * "OR" two arbitrary values together.
780 * Result is placed in the indicated location.
783 orvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
785 if (v1
->v_type
== V_NULL
) {
789 if (v2
->v_type
== V_NULL
) {
793 vres
->v_type
= v1
->v_type
;
794 vres
->v_subtype
= V_NOSUBTYPE
;
795 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
796 case TWOVAL(V_NUM
, V_NUM
):
797 vres
->v_num
= qor(v1
->v_num
, v2
->v_num
);
799 case TWOVAL(V_STR
, V_STR
):
800 vres
->v_str
= stringor(v1
->v_str
, v2
->v_str
);
801 if (vres
->v_str
== NULL
)
802 *vres
= error_value(E_STROR
);
804 case TWOVAL(V_OCTET
, V_OCTET
):
805 vres
->v_type
= V_STR
;
806 vres
->v_str
= charstring(*v1
->v_octet
| *v2
->v_octet
);
808 case TWOVAL(V_STR
, V_OCTET
):
809 vres
->v_str
= charstring(*v1
->v_str
->s_str
|
812 case TWOVAL(V_OCTET
, V_STR
):
813 vres
->v_type
= V_STR
;
814 vres
->v_str
= charstring(*v1
->v_octet
|
818 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
821 if (v2
->v_type
< 0) {
822 vres
->v_type
= v2
->v_type
;
825 *vres
= error_value(E_OR
);
828 *vres
= objcall(OBJ_OR
, v1
, v2
, NULL_VALUE
);
835 * "~" two values, returns the "symmetric difference" bitwise xor(v1, v2) for
836 * strings, octets and real numbers, and a user-defined function if at least
837 * one of v1 and v2 is an object.
840 xorvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
842 vres
->v_type
= v1
->v_type
;
843 vres
->v_subtype
= V_NOSUBTYPE
;
844 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
845 case (TWOVAL(V_NUM
, V_NUM
)):
846 vres
->v_num
= qxor(v1
->v_num
, v2
->v_num
);
848 case (TWOVAL(V_STR
, V_STR
)):
849 vres
->v_str
= stringxor(v1
->v_str
, v2
->v_str
);
850 if (vres
->v_str
== NULL
)
851 *vres
= error_value(E_STRDIFF
);
853 case (TWOVAL(V_STR
, V_OCTET
)):
854 if (v1
->v_str
->s_len
) {
855 vres
->v_str
= stringcopy(v1
->v_str
);
856 *vres
->v_str
->s_str
^= *v2
->v_octet
;
858 vres
->v_str
= charstring(*v2
->v_octet
);
861 case (TWOVAL(V_OCTET
, V_STR
)):
862 if (v2
->v_str
->s_len
) {
863 vres
->v_str
= stringcopy(v2
->v_str
);
864 *vres
->v_str
->s_str
^= *v1
->v_octet
;
866 vres
->v_str
= charstring(*v1
->v_octet
);
869 case (TWOVAL(V_OCTET
, V_OCTET
)):
870 vres
->v_type
= V_STR
;
871 vres
->v_str
= charstring(*v1
->v_octet
^ *v2
->v_octet
);
874 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
)
875 *vres
= objcall(OBJ_XOR
, v1
, v2
, NULL_VALUE
);
877 *vres
= error_value(E_XOR
);
883 * "#" two values - abs(v1-v2) for numbers, user-defined for objects
886 hashopvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
890 vres
->v_type
= v1
->v_type
;
891 vres
->v_subtype
= V_NOSUBTYPE
;
892 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
893 case TWOVAL(V_NUM
, V_NUM
):
894 q
= qsub(v1
->v_num
, v2
->v_num
);
895 vres
->v_num
= qqabs(q
);
899 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
)
900 *vres
= objcall(OBJ_HASHOP
, v1
, v2
, NULL_VALUE
);
902 *vres
= error_value(E_HASHOP
);
908 compvalue(VALUE
*vp
, VALUE
*vres
)
911 vres
->v_type
= vp
->v_type
;
912 vres
->v_subtype
= V_NOSUBTYPE
;
913 switch (vp
->v_type
) {
915 vres
->v_num
= qcomp(vp
->v_num
);
918 vres
->v_str
= stringcomp(vp
->v_str
);
919 if (vres
->v_str
== NULL
)
920 *vres
= error_value(E_STRCOMP
);
923 vres
->v_type
= V_STR
;
924 vres
->v_str
= charstring(~*vp
->v_octet
);
927 *vres
= objcall(OBJ_COMP
, vp
, NULL_VALUE
, NULL_VALUE
);
930 *vres
= error_value(E_COMP
);
935 * "\" a value, user-defined only
938 backslashvalue(VALUE
*vp
, VALUE
*vres
)
940 if (vp
->v_type
== V_OBJ
)
941 *vres
= objcall(OBJ_BACKSLASH
, vp
, NULL_VALUE
, NULL_VALUE
);
943 *vres
= error_value(E_BACKSLASH
);
948 * "\" two values, for strings performs bitwise "AND-NOT" operation
949 * User defined for objects
952 setminusvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
954 vres
->v_type
= v1
->v_type
;
955 vres
->v_subtype
= V_NOSUBTYPE
;
956 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
957 case TWOVAL(V_NUM
, V_NUM
):
958 vres
->v_num
= qandnot(v1
->v_num
, v2
->v_num
);
960 case TWOVAL(V_STR
, V_STR
):
961 vres
->v_str
= stringdiff(v1
->v_str
, v2
->v_str
);
963 case TWOVAL(V_STR
, V_OCTET
):
964 vres
->v_str
= charstring(*v1
->v_str
->s_str
&
967 case TWOVAL(V_OCTET
, V_STR
):
968 vres
->v_type
= V_STR
;
969 vres
->v_str
= charstring(*v1
->v_octet
&
972 case TWOVAL(V_OCTET
, V_OCTET
):
973 vres
->v_type
= V_STR
;
974 vres
->v_str
= charstring(*v1
->v_octet
&
978 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
)
979 *vres
= objcall(OBJ_SETMINUS
, v1
, v2
,
982 *vres
= error_value(E_SETMINUS
);
988 * "#" a value, for strings and octets returns the number of nonzero bits
989 * in the value; user-defined for an object
992 contentvalue(VALUE
*vp
, VALUE
*vres
)
997 vres
->v_type
= V_NUM
;
998 vres
->v_subtype
= V_NOSUBTYPE
;
1000 switch (vp
->v_type
) {
1002 count
= stringcontent(vp
->v_str
);
1005 for (u
= *vp
->v_octet
; u
; u
>>= 1)
1009 count
= zpopcnt(vp
->v_num
->num
, 1);
1012 *vres
= objcall(OBJ_CONTENT
, vp
, NULL_VALUE
,
1016 *vres
= error_value(E_CONTENT
);
1019 vres
->v_num
= itoq(count
);
1024 * Approximate numbers by multiples of v2 using rounding criterion v3.
1025 * Result is placed in the indicated location.
1028 apprvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
1035 vres
->v_type
= v1
->v_type
;
1036 vres
->v_subtype
= V_NOSUBTYPE
;
1037 if (v1
->v_type
<= 0)
1041 switch(v2
->v_type
) {
1042 case V_NUM
: e
= v2
->v_num
;
1044 case V_NULL
: e
= conf
->epsilon
;
1047 *vres
= error_value(E_APPR2
);
1050 switch(v3
->v_type
) {
1051 case V_NUM
: if (qisfrac(v3
->v_num
)) {
1052 *vres
= error_value(E_APPR3
);
1055 R
= qtoi(v3
->v_num
);
1057 case V_NULL
: R
= conf
->appr
;
1060 *vres
= error_value(E_APPR3
);
1065 copyvalue(v1
, vres
);
1068 switch (v1
->v_type
) {
1070 vres
->v_num
= qmappr(v1
->v_num
, e
, R
);
1073 vres
->v_mat
= matappr(v1
->v_mat
, v2
, v3
);
1076 vres
->v_list
= listappr(v1
->v_list
, v2
, v3
);
1079 q1
= qmappr(v1
->v_com
->real
, e
, R
);
1080 q2
= qmappr(v1
->v_com
->imag
, e
, R
);
1082 vres
->v_type
= V_NUM
;
1095 *vres
= error_value(E_APPR
);
1102 * Round numbers to number of decimals specified by v2, type of rounding
1103 * specified by v3. Result placed in location vres.
1106 roundvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
1112 vres
->v_type
= v1
->v_type
;
1113 vres
->v_subtype
= V_NOSUBTYPE
;
1114 if (v1
->v_type
== V_MAT
) {
1115 vres
->v_mat
= matround(v1
->v_mat
, v2
, v3
);
1118 if (v1
->v_type
== V_LIST
) {
1119 vres
->v_list
= listround(v1
->v_list
, v2
, v3
);
1122 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
1123 *vres
= objcall(OBJ_ROUND
, v1
, v2
, v3
);
1127 switch (v2
->v_type
) {
1129 if (qisfrac(v2
->v_num
)) {
1130 *vres
= error_value(E_ROUND2
);
1133 places
= qtoi(v2
->v_num
);
1138 *vres
= error_value(E_ROUND2
);
1142 switch (v3
->v_type
) {
1144 if (qisfrac(v3
->v_num
)) {
1145 *vres
= error_value(E_ROUND3
);
1148 rnd
= qtoi(v3
->v_num
);
1154 *vres
= error_value(E_ROUND3
);
1157 switch(v1
->v_type
) {
1159 vres
->v_num
= qround(v1
->v_num
, places
, rnd
);
1162 q1
= qround(v1
->v_com
->real
, places
, rnd
);
1163 q2
= qround(v1
->v_com
->imag
, places
, rnd
);
1165 vres
->v_type
= V_NUM
;
1178 if (v1
->v_type
<= 0)
1180 *vres
= error_value(E_ROUND
);
1188 * Round numbers to number of binary digits specified by v2, type of rounding
1189 * specified by v3. Result placed in location vres.
1192 broundvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
1198 vres
->v_type
= v1
->v_type
;
1199 vres
->v_subtype
= V_NOSUBTYPE
;
1200 if (v1
->v_type
== V_MAT
) {
1201 vres
->v_mat
= matbround(v1
->v_mat
, v2
, v3
);
1204 if (v1
->v_type
== V_LIST
) {
1205 vres
->v_list
= listbround(v1
->v_list
, v2
, v3
);
1208 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
1209 *vres
= objcall(OBJ_BROUND
, v1
, v2
, v3
);
1213 switch (v2
->v_type
) {
1215 if (qisfrac(v2
->v_num
)) {
1216 *vres
= error_value(E_BROUND2
);
1219 places
= qtoi(v2
->v_num
);
1224 *vres
= error_value(E_BROUND2
);
1228 switch (v3
->v_type
) {
1230 if (qisfrac(v3
->v_num
)) {
1231 *vres
= error_value(E_BROUND3
);
1234 rnd
= qtoi(v3
->v_num
);
1240 *vres
= error_value(E_BROUND3
);
1243 switch(v1
->v_type
) {
1245 vres
->v_num
= qbround(v1
->v_num
, places
, rnd
);
1248 q1
= qbround(v1
->v_com
->real
, places
, rnd
);
1249 q2
= qbround(v1
->v_com
->imag
, places
, rnd
);
1251 vres
->v_type
= V_NUM
;
1264 if (v1
->v_type
<= 0)
1266 *vres
= error_value(E_BROUND
);
1272 * Take the integer part of an arbitrary value.
1273 * Result is placed in the indicated location.
1276 intvalue(VALUE
*vp
, VALUE
*vres
)
1280 vres
->v_type
= vp
->v_type
;
1281 vres
->v_subtype
= V_NOSUBTYPE
;
1282 switch (vp
->v_type
) {
1284 if (qisint(vp
->v_num
))
1285 vres
->v_num
= qlink(vp
->v_num
);
1287 vres
->v_num
= qint(vp
->v_num
);
1290 if (cisint(vp
->v_com
)) {
1291 vres
->v_com
= clink(vp
->v_com
);
1294 vres
->v_com
= c_int(vp
->v_com
);
1297 vres
->v_num
= qlink(c
->real
);
1298 vres
->v_type
= V_NUM
;
1303 vres
->v_mat
= matint(vp
->v_mat
);
1306 *vres
= objcall(OBJ_INT
, vp
, NULL_VALUE
, NULL_VALUE
);
1309 if (vp
->v_type
<= 0)
1311 *vres
= error_value(E_INT
);
1318 * Take the fractional part of an arbitrary value.
1319 * Result is placed in the indicated location.
1322 fracvalue(VALUE
*vp
, VALUE
*vres
)
1326 vres
->v_type
= vp
->v_type
;
1327 vres
->v_subtype
= V_NOSUBTYPE
;
1328 switch (vp
->v_type
) {
1330 if (qisint(vp
->v_num
))
1331 vres
->v_num
= qlink(&_qzero_
);
1333 vres
->v_num
= qfrac(vp
->v_num
);
1336 if (cisint(vp
->v_com
)) {
1337 vres
->v_num
= clink(&_qzero_
);
1338 vres
->v_type
= V_NUM
;
1341 vres
->v_com
= c_frac(vp
->v_com
);
1344 vres
->v_num
= qlink(c
->real
);
1345 vres
->v_type
= V_NUM
;
1350 vres
->v_mat
= matfrac(vp
->v_mat
);
1353 *vres
= objcall(OBJ_FRAC
, vp
, NULL_VALUE
, NULL_VALUE
);
1358 *vres
= error_value(E_FRAC
);
1365 * Increment an arbitrary value by one.
1366 * Result is placed in the indicated location.
1369 incvalue(VALUE
*vp
, VALUE
*vres
)
1371 vres
->v_type
= vp
->v_type
;
1372 switch (vp
->v_type
) {
1374 vres
->v_num
= qinc(vp
->v_num
);
1377 vres
->v_com
= c_addq(vp
->v_com
, &_qone_
);
1380 *vres
= objcall(OBJ_INC
, vp
, NULL_VALUE
, NULL_VALUE
);
1383 *vres
->v_octet
= *vp
->v_octet
+ 1;
1386 vres
->v_octet
= vp
->v_octet
+ 1;
1389 vres
->v_addr
= vp
->v_addr
+ 1;
1393 *vres
= error_value(E_INCV
);
1396 vres
->v_subtype
= vp
->v_subtype
;
1401 * Decrement an arbitrary value by one.
1402 * Result is placed in the indicated location.
1405 decvalue(VALUE
*vp
, VALUE
*vres
)
1407 vres
->v_type
= vp
->v_type
;
1408 switch (vp
->v_type
) {
1410 vres
->v_num
= qdec(vp
->v_num
);
1413 vres
->v_com
= c_addq(vp
->v_com
, &_qnegone_
);
1416 *vres
= objcall(OBJ_DEC
, vp
, NULL_VALUE
, NULL_VALUE
);
1419 *vres
->v_octet
= *vp
->v_octet
- 1;
1422 vres
->v_octet
= vp
->v_octet
- 1;
1425 vres
->v_addr
= vp
->v_addr
- 1;
1428 if (vp
->v_type
>= 0)
1429 *vres
= error_value(E_DECV
);
1432 vres
->v_subtype
= vp
->v_subtype
;
1437 * Produce the 'conjugate' of an arbitrary value.
1438 * Result is placed in the indicated location.
1439 * (Example: complex conjugate.)
1442 conjvalue(VALUE
*vp
, VALUE
*vres
)
1444 vres
->v_type
= vp
->v_type
;
1445 vres
->v_subtype
= V_NOSUBTYPE
;
1446 switch (vp
->v_type
) {
1448 vres
->v_num
= qlink(vp
->v_num
);
1451 vres
->v_com
= comalloc();
1452 qfree(vres
->v_com
->real
);
1453 qfree(vres
->v_com
->imag
)
1454 vres
->v_com
->real
= qlink(vp
->v_com
->real
);
1455 vres
->v_com
->imag
= qneg(vp
->v_com
->imag
);
1458 vres
->v_mat
= matconj(vp
->v_mat
);
1461 *vres
= objcall(OBJ_CONJ
, vp
, NULL_VALUE
, NULL_VALUE
);
1464 if (vp
->v_type
<= 0) {
1465 vres
->v_type
= vp
->v_type
;
1468 *vres
= error_value(E_CONJ
);
1475 * Take the square root of an arbitrary value within the specified error.
1476 * Result is placed in the indicated location.
1479 sqrtvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
1485 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
1486 *vres
= objcall(OBJ_SQRT
, v1
, v2
, v3
);
1489 vres
->v_type
= v1
->v_type
;
1490 vres
->v_subtype
= V_NOSUBTYPE
;
1491 if (v1
->v_type
<= 0) {
1492 vres
->v_type
= v1
->v_type
;
1495 if (v2
->v_type
== V_NULL
) {
1498 if (v2
->v_type
!= V_NUM
|| qiszero(v2
->v_num
)) {
1499 *vres
= error_value(E_SQRT2
);
1504 if (v3
->v_type
== V_NULL
) {
1507 if (v3
->v_type
!= V_NUM
|| qisfrac(v3
->v_num
)) {
1508 *vres
= error_value(E_SQRT3
);
1511 R
= qtoi(v3
->v_num
);
1513 switch (v1
->v_type
) {
1515 if (!qisneg(v1
->v_num
)) {
1516 vres
->v_num
= qsqrt(v1
->v_num
, q
, R
);
1519 tmp
= qneg(v1
->v_num
);
1522 c
->imag
= qsqrt(tmp
, q
, R
);
1525 vres
->v_type
= V_COM
;
1528 vres
->v_com
= c_sqrt(v1
->v_com
, q
, R
);
1531 *vres
= error_value(E_SQRT
);
1536 vres
->v_num
= qlink(c
->real
);
1537 vres
->v_type
= V_NUM
;
1544 * Take the Nth root of an arbitrary value within the specified error.
1545 * Result is placed in the indicated location.
1548 * v1 value to take root of
1549 * v2 value specifying root to take
1550 * v3 value specifying error
1554 rootvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
1560 vres
->v_subtype
= V_NOSUBTYPE
;
1561 if (v1
->v_type
<= 0) {
1562 vres
->v_type
= v1
->v_type
;
1565 if (v2
->v_type
!= V_NUM
) {
1566 *vres
= error_value(E_ROOT2
);
1570 if (qisneg(q2
) || qiszero(q2
) || qisfrac(q2
)) {
1571 *vres
= error_value(E_ROOT2
);
1574 if (v3
->v_type
!= V_NUM
|| qiszero(v3
->v_num
)) {
1575 *vres
= error_value(E_ROOT3
);
1579 switch (v1
->v_type
) {
1581 if (!qisneg(v1
->v_num
)) {
1582 vres
->v_num
= qroot(v1
->v_num
, q2
, q3
);
1583 if (vres
->v_num
== NULL
)
1584 *vres
= error_value(E_ROOT4
);
1585 vres
->v_type
= V_NUM
;
1588 ctmp
.real
= v1
->v_num
;
1589 ctmp
.imag
= &_qzero_
;
1591 c
= c_root(&ctmp
, q2
, q3
);
1594 c
= c_root(v1
->v_com
, q2
, q3
);
1597 *vres
= objcall(OBJ_ROOT
, v1
, v2
, v3
);
1600 *vres
= error_value(E_ROOT
);
1604 *vres
= error_value(E_ROOT4
);
1608 vres
->v_type
= V_COM
;
1610 vres
->v_num
= qlink(c
->real
);
1611 vres
->v_type
= V_NUM
;
1618 * Take the absolute value of an arbitrary value within the specified error.
1619 * Result is placed in the indicated location.
1622 absvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
1626 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
1627 *vres
= objcall(OBJ_ABS
, v1
, v2
, NULL_VALUE
);
1630 vres
->v_subtype
= V_NOSUBTYPE
;
1631 if (v1
->v_type
<= 0) {
1632 vres
->v_type
= v1
->v_type
;
1635 switch (v1
->v_type
) {
1637 if (qisneg(v1
->v_num
))
1638 q
= qneg(v1
->v_num
);
1640 q
= qlink(v1
->v_num
);
1643 if (v2
->v_type
!= V_NUM
|| qiszero(v2
->v_num
)) {
1644 *vres
= error_value(E_ABS2
);
1647 q
= qhypot(v1
->v_com
->real
, v1
->v_com
->imag
, v2
->v_num
);
1650 *vres
= error_value(E_ABS
);
1654 vres
->v_type
= V_NUM
;
1659 * Calculate the norm of an arbitrary value.
1660 * Result is placed in the indicated location.
1661 * The norm is the square of the absolute value.
1664 normvalue(VALUE
*vp
, VALUE
*vres
)
1668 vres
->v_type
= vp
->v_type
;
1669 vres
->v_subtype
= V_NOSUBTYPE
;
1670 if (vp
->v_type
<= 0) {
1671 vres
->v_type
= vp
->v_type
;
1674 switch (vp
->v_type
) {
1676 vres
->v_num
= qsquare(vp
->v_num
);
1679 q1
= qsquare(vp
->v_com
->real
);
1680 q2
= qsquare(vp
->v_com
->imag
);
1681 vres
->v_num
= qqadd(q1
, q2
);
1682 vres
->v_type
= V_NUM
;
1687 *vres
= objcall(OBJ_NORM
, vp
, NULL_VALUE
, NULL_VALUE
);
1690 *vres
= error_value(E_NORM
);
1697 * Shift a value left or right by the specified number of bits.
1698 * Negative shift value means shift the direction opposite the selected dir.
1699 * Right shifts are defined to lose bits off the low end of the number.
1700 * Result is placed in the indicated location.
1705 * rightshift TRUE if shift right instead of left
1709 shiftvalue(VALUE
*v1
, VALUE
*v2
, BOOL rightshift
, VALUE
*vres
)
1716 vres
->v_subtype
= V_NOSUBTYPE
;
1717 if (v1
->v_type
<= 0) {
1718 vres
->v_type
= v1
->v_type
;
1721 if ((v2
->v_type
!= V_NUM
) || (qisfrac(v2
->v_num
))) {
1722 *vres
= error_value(E_SHIFT2
);
1725 if (v1
->v_type
!= V_OBJ
) {
1726 if (zge31b(v2
->v_num
->num
)) {
1727 *vres
= error_value(E_SHIFT2
);
1730 n
= qtoi(v2
->v_num
);
1734 vres
->v_type
= v1
->v_type
;
1735 switch (v1
->v_type
) {
1737 if (qisfrac(v1
->v_num
)) {
1738 *vres
= error_value(E_SHIFT
);
1741 vres
->v_num
= qshift(v1
->v_num
, n
);
1744 if (qisfrac(v1
->v_com
->real
) ||
1745 qisfrac(v1
->v_com
->imag
)) {
1746 *vres
= error_value(E_SHIFT
);
1749 c
= c_shift(v1
->v_com
, n
);
1754 vres
->v_num
= qlink(c
->real
);
1755 vres
->v_type
= V_NUM
;
1759 vres
->v_mat
= matshift(v1
->v_mat
, n
);
1762 vres
->v_str
= stringshift(v1
->v_str
, n
);
1763 if (vres
->v_str
== NULL
)
1764 *vres
= error_value(E_STRSHIFT
);
1767 vres
->v_type
= V_STR
;
1768 if (n
>= 8 || n
<= -8)
1771 ch
= (unsigned int) *v1
->v_octet
<< n
;
1773 ch
= (unsigned int) *v1
->v_octet
>> -n
;
1774 vres
->v_str
= charstring(ch
);
1778 *vres
= objcall(OBJ_SHIFT
, v1
, v2
, NULL_VALUE
);
1781 tmp
.v_num
= qneg(v2
->v_num
);
1783 *vres
= objcall(OBJ_SHIFT
, v1
, &tmp
, NULL_VALUE
);
1787 *vres
= error_value(E_SHIFT
);
1794 * Scale a value by a power of two.
1795 * Result is placed in the indicated location.
1798 scalevalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
1802 vres
->v_subtype
= V_NOSUBTYPE
;
1803 if (v1
->v_type
<= 0) {
1804 vres
->v_type
= v1
->v_type
;
1807 if ((v2
->v_type
!= V_NUM
) || qisfrac(v2
->v_num
)) {
1808 *vres
= error_value(E_SCALE2
);
1811 if (v1
->v_type
!= V_OBJ
) {
1812 if (zge31b(v2
->v_num
->num
)) {
1813 *vres
= error_value(E_SCALE2
);
1816 n
= qtoi(v2
->v_num
);
1818 vres
->v_type
= v1
->v_type
;
1819 switch (v1
->v_type
) {
1821 vres
->v_num
= qscale(v1
->v_num
, n
);
1824 vres
->v_com
= c_scale(v1
->v_com
, n
);
1827 vres
->v_mat
= matscale(v1
->v_mat
, n
);
1830 *vres
= objcall(OBJ_SCALE
, v1
, v2
, NULL_VALUE
);
1833 *vres
= error_value(E_SCALE
);
1840 * Raise a value to an power.
1841 * Result is placed in the indicated location.
1844 powvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
1846 NUMBER
*real_v2
; /* real part of v2 */
1849 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
1850 *vres
= objcall(OBJ_POW
, v1
, v2
, NULL_VALUE
);
1853 vres
->v_type
= v1
->v_type
;
1854 vres
->v_subtype
= V_NOSUBTYPE
;
1855 if (v1
->v_type
<= 0 && v1
->v_type
!= -E_1OVER0
)
1857 if (v2
->v_type
<= 0) {
1858 vres
->v_type
= v2
->v_type
;
1861 real_v2
= v2
->v_num
;
1863 /* case: raising to a real power */
1864 switch (v2
->v_type
) {
1867 /* deal with the division by 0 value */
1868 if (v1
->v_type
== -E_1OVER0
) {
1869 if (qisneg(real_v2
)) {
1870 vres
->v_type
= V_NUM
;
1871 vres
->v_num
= qlink(&_qzero_
);
1873 vres
->v_type
= -E_1OVER0
;
1878 /* raise something with a real exponent */
1879 switch (v1
->v_type
) {
1881 if (qiszero(v1
->v_num
)) {
1882 if (qisneg(real_v2
)) {
1883 *vres
= error_value(E_1OVER0
);
1886 /* 0 ^ non-neg is zero, including 0^0 */
1887 vres
->v_type
= V_NUM
;
1888 vres
->v_num
= qlink(&_qzero_
);
1889 } else if (qisint(real_v2
)) {
1890 vres
->v_num
= qpowi(v1
->v_num
, real_v2
);
1892 vres
->v_type
= V_NUM
;
1893 vres
->v_num
= qlink(&_qzero_
);
1894 powervalue(v1
, v2
, NULL
, vres
);
1898 if (qisint(real_v2
)) {
1899 vres
->v_com
= c_powi(v1
->v_com
, real_v2
);
1901 vres
->v_type
= V_NUM
;
1902 vres
->v_num
= qlink(&_qzero_
);
1903 powervalue(v1
, v2
, NULL
, vres
);
1905 if (vres
->v_type
== V_COM
) {
1909 vres
->v_num
= qlink(c
->real
);
1910 vres
->v_type
= V_NUM
;
1915 vres
->v_mat
= matpowi(v1
->v_mat
, real_v2
);
1918 *vres
= error_value(E_POWI
);
1925 /* deal with the division by 0 value */
1926 if (v1
->v_type
== -E_1OVER0
) {
1927 if (cisreal(v2
->v_com
) && qisneg(real_v2
)) {
1928 vres
->v_type
= V_NUM
;
1929 vres
->v_num
= qlink(&_qzero_
);
1931 vres
->v_type
= -E_1OVER0
;
1936 /* raise something with a real exponent */
1937 switch (v1
->v_type
) {
1939 if (qiszero(v1
->v_num
)) {
1940 if (cisreal(v2
->v_com
) && qisneg(real_v2
)) {
1941 *vres
= error_value(E_1OVER0
);
1945 * 0 ^ real non-neg is zero
1946 * 0 ^ complex is zero
1948 vres
->v_type
= V_NUM
;
1949 vres
->v_num
= qlink(&_qzero_
);
1951 if (cisreal(v2
->v_com
) && qisint(real_v2
)) {
1952 vres
->v_num
= qpowi(v1
->v_num
, real_v2
);
1954 vres
->v_type
= V_NUM
;
1955 vres
->v_num
= qlink(&_qzero_
);
1956 powervalue(v1
, v2
, NULL
, vres
);
1958 if (vres
->v_type
== V_COM
) {
1962 vres
->v_num
= qlink(c
->real
);
1963 vres
->v_type
= V_NUM
;
1968 if (cisreal(v2
->v_com
) && qisint(real_v2
)) {
1969 vres
->v_com
= c_powi(v1
->v_com
, real_v2
);
1971 vres
->v_type
= V_NUM
;
1972 vres
->v_num
= qlink(&_qzero_
);
1973 powervalue(v1
, v2
, NULL
, vres
);
1975 if (vres
->v_type
== V_COM
) {
1979 vres
->v_num
= qlink(c
->real
);
1980 vres
->v_type
= V_NUM
;
1985 *vres
= error_value(E_POWI
);
1990 /* unspported exponent type */
1992 *vres
= error_value(E_POWI2
);
2000 * Raise one value to another value's power, within the specified error.
2001 * Result is placed in the indicated location. If v3 is NULL, the
2002 * value conf->epsiilon is used.
2005 powervalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
2008 COMPLEX
*c
, ctmp1
, ctmp2
;
2010 vres
->v_subtype
= V_NOSUBTYPE
;
2011 if (v1
->v_type
<= 0) {
2012 vres
->v_type
= v1
->v_type
;
2015 if (v1
->v_type
!= V_NUM
&& v1
->v_type
!= V_COM
) {
2016 *vres
= error_value(E_POWER
);
2019 if (v2
->v_type
!= V_NUM
&& v2
->v_type
!= V_COM
) {
2020 *vres
= error_value(E_POWER2
);
2024 /* NULL epsilon means use built-in epslion value */
2026 epsilon
= conf
->epsilon
;
2028 if (v3
->v_type
!= V_NUM
|| qiszero(v3
->v_num
)) {
2029 *vres
= error_value(E_POWER3
);
2032 epsilon
= v3
->v_num
;
2034 if (qiszero(epsilon
)) {
2035 *vres
= error_value(E_POWER3
);
2039 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
2040 case TWOVAL(V_NUM
, V_NUM
):
2041 if (qisneg(v1
->v_num
)) {
2042 ctmp1
.real
= v1
->v_num
;
2043 ctmp1
.imag
= &_qzero_
;
2045 ctmp2
.real
= v2
->v_num
;
2046 ctmp2
.imag
= &_qzero_
;
2048 c
= c_power(&ctmp1
, &ctmp2
, epsilon
);
2051 vres
->v_num
= qpower(v1
->v_num
, v2
->v_num
, epsilon
);
2052 vres
->v_type
= V_NUM
;
2053 if (vres
->v_num
== NULL
)
2054 *vres
= error_value(E_POWER4
);
2056 case TWOVAL(V_NUM
, V_COM
):
2057 ctmp1
.real
= v1
->v_num
;
2058 ctmp1
.imag
= &_qzero_
;
2060 c
= c_power(&ctmp1
, v2
->v_com
, epsilon
);
2062 case TWOVAL(V_COM
, V_NUM
):
2063 ctmp2
.real
= v2
->v_num
;
2064 ctmp2
.imag
= &_qzero_
;
2066 c
= c_power(v1
->v_com
, &ctmp2
, epsilon
);
2068 case TWOVAL(V_COM
, V_COM
):
2069 c
= c_power(v1
->v_com
, v2
->v_com
, epsilon
);
2072 *vres
= error_value(E_POWER
);
2076 * Here for any complex result.
2078 vres
->v_type
= V_COM
;
2081 vres
->v_num
= qlink(c
->real
);
2082 vres
->v_type
= V_NUM
;
2089 * Divide one arbitrary value by another one.
2090 * Result is placed in the indicated location.
2093 divvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
2100 vres
->v_type
= v1
->v_type
;
2101 vres
->v_subtype
= V_NOSUBTYPE
;
2102 if (v1
->v_type
<= 0)
2104 if (v2
->v_type
<= 0) {
2105 if (testvalue(v1
) && v2
->v_type
== -E_1OVER0
) {
2106 vres
->v_type
= V_NUM
;
2107 vres
->v_num
= qlink(&_qzero_
);
2110 vres
->v_type
= v2
->v_type
;
2113 if (!testvalue(v2
)) {
2115 *vres
= error_value(E_1OVER0
);
2117 *vres
= error_value(E_0OVER0
);
2120 vres
->v_type
= v1
->v_type
;
2121 switch (TWOVAL(v1
->v_type
, v2
->v_type
)) {
2122 case TWOVAL(V_NUM
, V_NUM
):
2123 vres
->v_num
= qqdiv(v1
->v_num
, v2
->v_num
);
2125 case TWOVAL(V_COM
, V_NUM
):
2126 vres
->v_com
= c_divq(v1
->v_com
, v2
->v_num
);
2128 case TWOVAL(V_NUM
, V_COM
):
2129 if (qiszero(v1
->v_num
)) {
2130 vres
->v_num
= qlink(&_qzero_
);
2133 ctmp
.real
= v1
->v_num
;
2134 ctmp
.imag
= &_qzero_
;
2136 vres
->v_com
= c_div(&ctmp
, v2
->v_com
);
2137 vres
->v_type
= V_COM
;
2139 case TWOVAL(V_COM
, V_COM
):
2140 vres
->v_com
= c_div(v1
->v_com
, v2
->v_com
);
2143 vres
->v_num
= qlink(c
->real
);
2144 vres
->v_type
= V_NUM
;
2148 case TWOVAL(V_MAT
, V_NUM
):
2149 case TWOVAL(V_MAT
, V_COM
):
2150 invertvalue(v2
, &tmpval
);
2151 vres
->v_mat
= matmulval(v1
->v_mat
, &tmpval
);
2154 case TWOVAL(V_STR
, V_NUM
):
2155 q
= qinv(v2
->v_num
);
2156 vres
->v_str
= stringmul(q
, v1
->v_str
);
2158 if (vres
->v_str
== NULL
)
2159 *vres
= error_value(E_DIV
);
2162 if ((v1
->v_type
!= V_OBJ
) && (v2
->v_type
!= V_OBJ
)) {
2163 *vres
= error_value(E_DIV
);
2166 *vres
= objcall(OBJ_DIV
, v1
, v2
, NULL_VALUE
);
2173 * Divide one arbitrary value by another one keeping only the integer part.
2174 * Result is placed in the indicated location.
2177 quovalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
2183 vres
->v_type
= v1
->v_type
;
2184 vres
->v_subtype
= V_NOSUBTYPE
;
2185 if (v1
->v_type
<= 0)
2188 if (v1
->v_type
== V_MAT
) {
2189 vres
->v_mat
= matquoval(v1
->v_mat
, v2
, v3
);
2192 if (v1
->v_type
== V_LIST
) {
2193 vres
->v_list
= listquo(v1
->v_list
, v2
, v3
);
2196 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
2197 *vres
= objcall(OBJ_QUO
, v1
, v2
, v3
);
2200 if (v2
->v_type
<= 0) {
2201 vres
->v_type
= v2
->v_type
;
2204 if (v2
->v_type
!= V_NUM
) {
2205 *vres
= error_value(E_QUO2
);
2209 switch (v3
->v_type
) {
2211 if (qisfrac(v3
->v_num
)) {
2212 *vres
= error_value(E_QUO3
);
2215 rnd
= qtoi(v3
->v_num
);
2221 *vres
= error_value(E_QUO3
);
2224 switch (v1
->v_type
) {
2226 vres
->v_num
= qquo(v1
->v_num
, v2
->v_num
, rnd
);
2229 q1
= qquo(v1
->v_com
->real
, v2
->v_num
, rnd
);
2230 q2
= qquo(v1
->v_com
->imag
, v2
->v_num
, rnd
);
2233 vres
->v_type
= V_NUM
;
2245 *vres
= error_value(E_QUO
);
2252 * Divide one arbitrary value by another one keeping only the remainder.
2253 * Result is placed in the indicated location.
2256 modvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*v3
, VALUE
*vres
)
2262 vres
->v_type
= v1
->v_type
;
2263 vres
->v_subtype
= V_NOSUBTYPE
;
2264 if (v1
->v_type
<= 0)
2267 if (v1
->v_type
== V_MAT
) {
2268 vres
->v_mat
= matmodval(v1
->v_mat
, v2
, v3
);
2271 if (v1
->v_type
== V_LIST
) {
2272 vres
->v_list
= listmod(v1
->v_list
, v2
, v3
);
2275 if (v1
->v_type
== V_OBJ
|| v2
->v_type
== V_OBJ
) {
2276 *vres
= objcall(OBJ_MOD
, v1
, v2
, v3
);
2279 if (v2
->v_type
<= 0) {
2280 vres
->v_type
= v2
->v_type
;
2283 if (v2
->v_type
!= V_NUM
) {
2284 *vres
= error_value(E_MOD2
);
2288 switch (v3
->v_type
) {
2290 if (qisfrac(v3
->v_num
)) {
2291 *vres
= error_value(E_MOD3
);
2294 rnd
= qtoi(v3
->v_num
);
2300 *vres
= error_value(E_MOD3
);
2303 switch (v1
->v_type
) {
2305 vres
->v_num
= qmod(v1
->v_num
, v2
->v_num
, rnd
);
2308 q1
= qmod(v1
->v_com
->real
, v2
->v_num
, rnd
);
2309 q2
= qmod(v1
->v_com
->imag
, v2
->v_num
, rnd
);
2312 vres
->v_type
= V_NUM
;
2324 *vres
= error_value(E_MOD
);
2331 * Test an arbitrary value to see if it is equal to "zero".
2332 * The definition of zero varies depending on the value type. For example,
2333 * the null string is "zero", and a matrix with zero values is "zero".
2334 * Returns TRUE if value is not equal to zero.
2337 testvalue(VALUE
*vp
)
2343 switch (vp
->v_type
) {
2345 return !qiszero(vp
->v_num
);
2347 return !ciszero(vp
->v_com
);
2349 return stringtest(vp
->v_str
);
2351 return mattest(vp
->v_mat
);
2353 for (ep
= vp
->v_list
->l_first
; ep
; ep
= ep
->e_next
) {
2354 if (testvalue(&ep
->e_value
))
2359 return (vp
->v_assoc
->a_count
!= 0);
2361 return validid(vp
->v_file
);
2363 break; /* hack to get gcc on SunOS to be quiet */
2365 val
= objcall(OBJ_TEST
, vp
, NULL_VALUE
, NULL_VALUE
);
2366 return (val
.v_int
!= 0);
2368 for (i
=0; i
< vp
->v_block
->datalen
; ++i
) {
2369 if (vp
->v_block
->data
[i
]) {
2375 return (*vp
->v_octet
!= 0);
2377 if (vp
->v_nblock
->blk
->data
== NULL
)
2379 for (i
=0; i
< vp
->v_nblock
->blk
->datalen
; ++i
) {
2380 if (vp
->v_nblock
->blk
->data
[i
]) {
2388 /* hack to get gcc on SunOS to be quiet */
2394 * Compare two values for equality.
2395 * Returns TRUE if the two values differ.
2398 comparevalue(VALUE
*v1
, VALUE
*v2
)
2403 if ((v1
->v_type
== V_OBJ
) || (v2
->v_type
== V_OBJ
)) {
2404 val
= objcall(OBJ_CMP
, v1
, v2
, NULL_VALUE
);
2405 return (val
.v_int
!= 0);
2409 if (v1
->v_type
== V_OCTET
) {
2410 if (v2
->v_type
== V_OCTET
)
2411 return (*v1
->v_octet
!= *v2
->v_octet
);
2412 if (v2
->v_type
== V_STR
)
2413 return (*v1
->v_octet
!= (OCTET
) *v2
->v_str
->s_str
)
2414 || (v2
->v_str
->s_len
!= 1);
2415 if (v2
->v_type
!= V_NUM
|| qisfrac(v2
->v_num
) ||
2416 qisneg(v2
->v_num
) || v2
->v_num
->num
.len
> 1)
2418 return (*v2
->v_num
->num
.v
!= *v1
->v_octet
);
2420 if (v2
->v_type
== V_OCTET
)
2421 return comparevalue(v2
, v1
);
2422 if (v1
->v_type
!= v2
->v_type
)
2424 if (v1
->v_type
<= 0)
2426 switch (v1
->v_type
) {
2428 r
= qcmp(v1
->v_num
, v2
->v_num
);
2431 r
= c_cmp(v1
->v_com
, v2
->v_com
);
2434 r
= stringcmp(v1
->v_str
, v2
->v_str
);
2437 r
= matcmp(v1
->v_mat
, v2
->v_mat
);
2440 r
= listcmp(v1
->v_list
, v2
->v_list
);
2443 r
= assoccmp(v1
->v_assoc
, v2
->v_assoc
);
2446 r
= (v1
->v_file
!= v2
->v_file
);
2449 r
= randcmp(v1
->v_rand
, v2
->v_rand
);
2452 r
= randomcmp(v1
->v_random
, v2
->v_random
);
2455 r
= config_cmp(v1
->v_config
, v2
->v_config
);
2458 r
= hash_cmp(v1
->v_hash
, v2
->v_hash
);
2461 r
= blk_cmp(v1
->v_block
, v2
->v_block
);
2464 r
= (v1
->v_octet
!= v2
->v_octet
);
2467 return (v1
->v_nblock
!= v2
->v_nblock
);
2469 return (v1
->v_addr
!= v2
->v_addr
);
2471 return (v1
->v_octet
!= v2
->v_octet
);
2473 return (v1
->v_str
!= v2
->v_str
);
2475 return (v1
->v_num
!= v2
->v_num
);
2477 math_error("Illegal values for comparevalue");
2484 acceptvalue(VALUE
*v1
, VALUE
*v2
)
2490 index
= adduserfunc("accept");
2491 fp
= findfunc(index
);
2494 stack
->v_type
= V_ADDR
;
2495 stack
->v_subtype
= V_NOSUBTYPE
;
2498 stack
->v_type
= V_ADDR
;
2499 stack
->v_subtype
= V_NOSUBTYPE
;
2502 ret
= testvalue(stack
);
2506 return (!comparevalue(v1
, v2
));
2511 precvalue(VALUE
*v1
, VALUE
*v2
)
2519 index
= adduserfunc("precedes");
2520 fp
= findfunc(index
);
2523 stack
->v_type
= V_ADDR
;
2524 stack
->v_subtype
= V_NOSUBTYPE
;
2527 stack
->v_type
= V_ADDR
;
2528 stack
->v_subtype
= V_NOSUBTYPE
;
2531 ret
= testvalue(stack
);
2535 relvalue(v1
, v2
, &val
);
2536 if ((val
.v_type
== V_NUM
&& qisneg(val
.v_num
)) ||
2537 (val
.v_type
== V_COM
&& qisneg(val
.v_com
->imag
)))
2539 if (val
.v_type
== V_NULL
)
2540 r
= (v1
->v_type
< v2
->v_type
);
2552 val
.v_subtype
= V_NOSUBTYPE
;
2554 val
.v_num
= qlink(&_qone_
);
2556 val
.v_num
= qlink(&_qnegone_
);
2558 val
.v_num
= qlink(&_qzero_
);
2564 * Compare two values for their relative values.
2565 * Result is placed in the indicated location.
2568 relvalue(VALUE
*v1
, VALUE
*v2
, VALUE
*vres
)
2575 vres
->v_subtype
= V_NOSUBTYPE
;
2576 vres
->v_type
= V_NULL
;
2577 if ((v1
->v_type
== V_OBJ
) || (v2
->v_type
== V_OBJ
)) {
2578 *vres
= objcall(OBJ_REL
, v1
, v2
, NULL_VALUE
);
2581 switch(v1
->v_type
) {
2583 switch(v2
->v_type
) {
2585 r
= qrel(v1
->v_num
, v2
->v_num
);
2588 q
= itoq((long) *v2
->v_octet
);
2589 r
= qrel(v1
->v_num
, q
);
2593 r
= qrel(v1
->v_num
, v2
->v_com
->real
);
2594 i
= qrel(&_qzero_
, v2
->v_com
->imag
);
2601 switch(v2
->v_type
) {
2603 r
= qrel(v1
->v_com
->real
, v2
->v_num
);
2604 i
= qrel(v1
->v_com
->imag
, &_qzero_
);
2607 r
= qrel(v1
->v_com
->real
, v2
->v_com
->real
);
2608 i
= qrel(v1
->v_com
->imag
, v2
->v_com
->imag
);
2611 q
= itoq((long) *v2
->v_octet
);
2612 r
= qrel(v1
->v_com
->real
, q
);
2614 i
= qrel(v1
->v_com
->imag
, &_qzero_
);
2621 switch(v2
->v_type
) {
2623 r
= stringrel(v1
->v_str
, v2
->v_str
);
2626 r
= (unsigned char) *v1
->v_str
->s_str
2629 if (v1
->v_str
->s_len
== 0)
2632 r
= (v1
->v_str
->s_len
> 1);
2640 switch(v2
->v_type
) {
2642 q
= itoq((long) *v1
->v_octet
);
2643 r
= qrel(q
, v2
->v_num
);
2647 q
= itoq((long) *v1
->v_octet
);
2648 r
= qrel(q
, v2
->v_com
->real
);
2650 i
= qrel(&_qzero_
, v2
->v_com
->imag
);
2653 r
= *v1
->v_octet
- *v2
->v_octet
;
2657 (unsigned char) *v2
->v_str
->s_str
;
2659 if (v2
->v_str
->s_len
== 0)
2662 r
= -(v2
->v_str
->s_len
> 1);
2670 if (v2
->v_type
!= V_VPTR
)
2672 r
= (v1
->v_addr
- v2
->v_addr
);
2675 if (v2
->v_type
!= V_OPTR
)
2677 r
= (v1
->v_octet
- v2
->v_octet
);
2682 vres
->v_type
= V_NUM
;
2688 c
->real
= vres
->v_num
;
2691 c
->imag
= vres
->v_num
;
2692 vres
->v_type
= V_COM
;
2699 * Find a value representing sign or signs in a value
2700 * Result is placed in the indicated location.
2703 sgnvalue(VALUE
*vp
, VALUE
*vres
)
2707 vres
->v_type
= vp
->v_type
;
2708 switch (vp
->v_type
) {
2710 vres
->v_num
= qsign(vp
->v_num
);
2711 vres
->v_subtype
= vp
->v_subtype
;
2717 c
->real
= qsign(vp
->v_com
->real
);
2718 c
->imag
= qsign(vp
->v_com
->imag
);
2720 vres
->v_type
= V_COM
;
2721 vres
->v_subtype
= V_NOSUBTYPE
;
2724 vres
->v_type
= V_NUM
;
2725 vres
->v_subtype
= V_NOSUBTYPE
;
2726 vres
->v_num
= itoq((long) (*vp
->v_octet
!= 0));
2729 *vres
= objcall(OBJ_SGN
, vp
, NULL_VALUE
, NULL_VALUE
);
2733 *vres
= error_value(E_SGN
);
2740 userfunc(char *fname
, VALUE
*vp
)
2744 fp
= findfunc(adduserfunc(fname
));
2749 stack
->v_type
= V_ADDR
;
2750 stack
->v_subtype
= V_NOSUBTYPE
;
2758 * Print the value of a descriptor in one of several formats.
2759 * If flags contains PRINT_SHORT, then elements of arrays and lists
2760 * will not be printed. If flags contains PRINT_UNAMBIG, then quotes
2761 * are placed around strings and the null value is explicitly printed.
2764 printvalue(VALUE
*vp
, int flags
)
2771 if (userfunc("error_print", vp
))
2773 if (-type
>= E__BASE
)
2774 math_fmt("Error %d", -type
);
2776 math_fmt("System error %d", -type
);
2781 qprintnum(vp
->v_num
, MODE_DEFAULT
);
2782 if (conf
->traceflags
& TRACE_LINKS
)
2783 math_fmt("#%ld", vp
->v_num
->links
);
2786 comprint(vp
->v_com
);
2787 if (conf
->traceflags
& TRACE_LINKS
)
2788 math_fmt("##%ld", vp
->v_com
->links
);
2791 if (flags
& PRINT_UNAMBIG
)
2793 math_str(vp
->v_str
->s_str
);
2794 if (flags
& PRINT_UNAMBIG
)
2798 if (flags
& PRINT_UNAMBIG
)
2802 (void) objcall(OBJ_PRINT
, vp
, NULL_VALUE
, NULL_VALUE
);
2805 if (!userfunc("list_print", vp
))
2806 listprint(vp
->v_list
,
2807 ((flags
& PRINT_SHORT
) ? 0L : conf
->maxprint
));
2810 assocprint(vp
->v_assoc
,
2811 ((flags
& PRINT_SHORT
) ? 0L : conf
->maxprint
));
2814 if (!userfunc("mat_print", vp
))
2816 ((flags
& PRINT_SHORT
) ? 0L : conf
->maxprint
));
2819 if (!userfunc("file_print", vp
))
2820 printid(vp
->v_file
, flags
);
2823 randprint(vp
->v_rand
, flags
);
2826 randomprint(vp
->v_random
, flags
);
2829 config_print(vp
->v_config
);
2832 hash_print(vp
->v_hash
);
2835 if (!userfunc("blk_print", vp
))
2836 blk_print(vp
->v_block
);
2839 if (userfunc("octet_print", vp
))
2841 qtemp
= itoq((long) *vp
->v_octet
);
2842 qprintnum(qtemp
, MODE_DEFAULT
);
2846 math_fmt("o-ptr: %p", vp
->v_octet
);
2849 math_fmt("v-ptr: %p", vp
->v_addr
);
2852 math_fmt("s_ptr: %p", vp
->v_str
);
2855 math_fmt("n_ptr: %p", vp
->v_num
);
2858 if (!userfunc("nblk_print", vp
))
2859 nblock_print(vp
->v_nblock
);
2862 math_error("Printing unrecognized type of value");
2868 * Print an exact text representation of a value
2871 printestr(VALUE
*vp
)
2881 if (vp
->v_type
< 0) {
2882 math_fmt("error(%d)", -vp
->v_type
);
2885 switch(vp
->v_type
) {
2891 strprint(vp
->v_str
);
2895 qprintnum(vp
->v_num
, MODE_FRAC
);
2898 mode
= math_setmode(MODE_FRAC
);
2899 comprint(vp
->v_com
);
2904 ep
= vp
->v_list
->l_first
;
2906 printestr(&ep
->e_value
);
2907 while ((ep
= ep
->e_next
)) {
2909 printestr(&ep
->e_value
);
2917 math_str("(mat[])");
2920 for (i
= 0; i
< mp
->m_dim
; i
++) {
2926 math_fmt("%ld:%ld", min
, max
);
2928 math_fmt("%ld", max
+ 1);
2937 math_fmt("obj %s",objtypename(op
->o_actions
->oa_index
));
2938 i
= op
->o_actions
->oa_count
;
2944 if (vp
->v_type
== V_BLOCK
)
2947 math_fmt("\"%s\",", vp
->v_nblock
->name
);
2948 bp
= vp
->v_nblock
->blk
;
2951 math_fmt("%ld,%ld)", i
, bp
->blkchunk
);
2955 math_fmt("%d", *cp
);
2958 math_fmt("%d", *++cp
);
2965 math_str("\"???\"");
2981 * config_print - print a configuration value
2987 config_print(CONFIG
*cfg
)
2991 int tab_over
; /* TRUE => ok move over one tab stop */
2997 if (cfg
== NULL
|| cfg
->epsilon
== NULL
|| cfg
->prompt1
== NULL
||
2998 cfg
->prompt2
== NULL
) {
2999 math_error("CONFIG value is invalid");
3004 * print each element
3007 for (cp
= configs
; cp
->name
; cp
++) {
3009 /* skip if special all or duplicate maxerr value */
3010 if (cp
->type
== CONFIG_ALL
|| strcmp(cp
->name
, "maxerr") == 0 ||
3011 strcmp(cp
->name
, "ctrl-d") == 0)
3014 /* print tab if allowed */
3017 } else if (conf
->tab_ok
) {
3018 tab_over
= TRUE
; /* tab next time */
3021 /* print name and spaces */
3022 math_fmt("%s", cp
->name
);
3023 len
= 16 - strlen(cp
->name
);
3028 config_value(cfg
, cp
->type
, &tmp
);
3029 printvalue(&tmp
, PRINT_SHORT
| PRINT_UNAMBIG
);