2 ent-quatern.c -- Numeric types for SXEmacs
3 Copyright (C) 2005, 2006 Sebastian Freundt
5 Author: Sebastian Freundt
7 This file is part of SXEmacs
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
27 #include "sysproc.h" /* For qxe_getpid */
30 #include "ent-quatern.h"
32 quatern ent_scratch_quatern;
34 static ase_nullary_operation_f Qent_quatern_zero, Qent_quatern_one;
38 quatern_print(Lisp_Object obj, Lisp_Object printcharfun, int SXE_UNUSED(escapeflag))
40 Bufbyte *fstr = quatern_to_string(XQUATERN_DATA(obj), 10);
41 write_c_string((char*)fstr, printcharfun);
43 fstr = (Bufbyte *)NULL;
48 quatern_equal(Lisp_Object obj1, Lisp_Object obj2, int SXE_UNUSED(depth))
50 return quatern_eql(XQUATERN_DATA(obj1), XQUATERN_DATA(obj2));
54 quatern_hash(Lisp_Object obj, int SXE_UNUSED(depth))
56 return quatern_hashcode(XQUATERN_DATA(obj));
60 quatern_mark(Lisp_Object SXE_UNUSED(obj))
66 quatern_finalise(void *unused, int for_disksave)
70 "Can't dump an emacs containing "
71 "quaternionic objects", Qt);
75 static const struct lrecord_description quatern_description[] = {
76 { XD_OPAQUE_DATA_PTR, offsetof(Lisp_Quatern, data) },
80 DEFINE_BASIC_LRECORD_IMPLEMENTATION("quatern", quatern,
81 quatern_mark, quatern_print,
83 quatern_equal, quatern_hash,
84 quatern_description, Lisp_Quatern);
88 void quatern_init(quatern g)
90 bigz_init(quatern_z(g));
91 bigz_init(quatern_i(g));
92 bigz_init(quatern_j(g));
93 bigz_init(quatern_k(g));
96 void quatern_fini(quatern g)
98 bigz_fini(quatern_z(g));
99 bigz_fini(quatern_i(g));
100 bigz_fini(quatern_j(g));
101 bigz_fini(quatern_k(g));
104 unsigned long quatern_hashcode(quatern g)
106 return (bigz_hashcode(quatern_z(g)) ^
107 bigz_hashcode(quatern_i(g)) ^
108 bigz_hashcode(quatern_j(g)) ^
109 bigz_hashcode(quatern_k(g)));
112 Bufbyte *quatern_to_string(quatern g, int base)
114 Bufbyte *z_str, *i_str, *j_str, *k_str;
115 int z_len, i_len, j_len, k_len;
116 int sign_i, sign_j, sign_k, neg_i, neg_j, neg_k;
118 z_str = (Bufbyte*)bigz_to_string(quatern_z(g), base);
119 i_str = (Bufbyte*)bigz_to_string(quatern_i(g), base);
120 j_str = (Bufbyte*)bigz_to_string(quatern_j(g), base);
121 k_str = (Bufbyte*)bigz_to_string(quatern_k(g), base);
123 z_len = strlen((char*)z_str);
124 i_len = strlen((char*)i_str);
125 j_len = strlen((char*)j_str);
126 k_len = strlen((char*)k_str);
128 sign_i = bigz_sign(quatern_i(g));
129 sign_j = bigz_sign(quatern_j(g));
130 sign_k = bigz_sign(quatern_k(g));
131 neg_i = (sign_i >= 0) ? 1 : 0;
132 neg_j = (sign_j >= 0) ? 1 : 0;
133 neg_k = (sign_k >= 0) ? 1 : 0;
135 /* now append the imaginary string */
136 XREALLOC_ARRAY(z_str, Bufbyte, z_len +
143 z_str[z_len+neg_i+i_len+1] = '+';
145 z_str[z_len+neg_i+i_len+1+neg_j+j_len+1] = '+';
146 memmove(&z_str[z_len + neg_i],
149 memmove(&z_str[z_len + neg_i+i_len+1 + neg_j],
152 memmove(&z_str[z_len + neg_i+i_len+1 + neg_j+j_len+1 + neg_k],
155 z_str[z_len+neg_i+i_len] = 'i';
156 z_str[z_len+neg_i+i_len+1+neg_j+j_len] = 'j';
157 z_str[z_len+neg_i+i_len+1+neg_j+j_len+1+neg_k+k_len] = 'k';
158 z_str[z_len+neg_i+i_len+1+neg_j+j_len+1+neg_k+k_len+1] = '\0';
164 /***** Quatern: converting assignments *****/
165 void quatern_set(quatern g1,quatern g2)
167 bigz_set(quatern_z(g1), quatern_z(g2));
168 bigz_set(quatern_i(g1), quatern_i(g2));
169 bigz_set(quatern_j(g1), quatern_j(g2));
170 bigz_set(quatern_k(g1), quatern_k(g2));
173 void quatern_set_long(quatern g, long l)
175 bigz_set_long(quatern_z(g), l);
176 bigz_set_long(quatern_i(g), 0L);
177 bigz_set_long(quatern_j(g), 0L);
178 bigz_set_long(quatern_k(g), 0L);
181 void quatern_set_long_long_long_long(
182 quatern g, long l1, long l2, long l3, long l4)
184 bigz_set_long(quatern_z(g), l1);
185 bigz_set_long(quatern_i(g), l2);
186 bigz_set_long(quatern_j(g), l3);
187 bigz_set_long(quatern_k(g), l4);
190 void quatern_set_ulong(quatern g, unsigned long ul)
192 bigz_set_ulong(quatern_z(g), ul);
193 bigz_set_ulong(quatern_i(g), 0UL);
194 bigz_set_ulong(quatern_j(g), 0UL);
195 bigz_set_ulong(quatern_k(g), 0UL);
198 void quatern_set_ulong_ulong_ulong_ulong(
199 quatern g, unsigned long ul1, unsigned long ul2,
200 unsigned long ul3, unsigned long ul4)
202 bigz_set_ulong(quatern_z(g), ul1);
203 bigz_set_ulong(quatern_i(g), ul2);
204 bigz_set_ulong(quatern_j(g), ul3);
205 bigz_set_ulong(quatern_k(g), ul4);
208 void quatern_set_bigz(quatern g, bigz z)
210 bigz_set(quatern_z(g), z);
211 bigz_set_long(quatern_i(g), 0L);
212 bigz_set_long(quatern_j(g), 0L);
213 bigz_set_long(quatern_k(g), 0L);
216 void quatern_set_bigz_bigz_bigz_bigz(
217 quatern g, bigz z1, bigz z2, bigz z3, bigz z4)
219 bigz_set(quatern_z(g), z1);
220 bigz_set(quatern_i(g), z2);
221 bigz_set(quatern_j(g), z3);
222 bigz_set(quatern_k(g), z4);
225 /* void bigc_set_quatern(bigc c, quatern g)
227 * bigc_set_bigfr_bigfr(quatern_z(g), z1);
231 /***** Quatern: comparisons *****/
232 int quatern_eql(quatern g1, quatern g2)
234 return ((bigz_eql(quatern_z(g1), quatern_z(g2))) &&
235 (bigz_eql(quatern_i(g1), quatern_i(g2))) &&
236 (bigz_eql(quatern_j(g1), quatern_j(g2))) &&
237 (bigz_eql(quatern_k(g1), quatern_k(g2))));
240 /***** Quatern: arithmetic *****/
242 void quatern_abs(bigfr res, quatern g)
245 /* the absolute archimedean valuation of a+bi is defined as:
246 * (a^2 + b^2 + c^2 + d^2)^(1/2)
248 bigz accu1, accu2, bz;
253 bigz_mul(accu1, quatern_z(g), quatern_z(g));
254 bigz_mul(accu2, quatern_i(g), quatern_i(g));
255 bigz_add(bz, accu1, accu2);
257 bigfr_set_bigz(res, bz);
258 bigfr_sqrt(res, res);
266 void quatern_norm(bigz res, quatern g)
268 /* norm is the product of g and conj(g) */
269 quatern_conj(ent_scratch_quatern, g);
270 quatern_mul(ent_scratch_quatern, g, ent_scratch_quatern);
271 bigz_set(res, quatern_z(ent_scratch_quatern));
274 void quatern_neg(quatern res, quatern g)
276 /* negation is defined point-wise */
277 bigz_neg(quatern_z(res), quatern_z(g));
278 bigz_neg(quatern_i(res), quatern_i(g));
279 bigz_neg(quatern_j(res), quatern_j(g));
280 bigz_neg(quatern_k(res), quatern_k(g));
283 void quatern_conj(quatern res, quatern g)
285 bigz_set(quatern_z(res), quatern_z(g));
286 bigz_neg(quatern_i(res), quatern_i(g));
287 bigz_neg(quatern_j(res), quatern_j(g));
288 bigz_neg(quatern_k(res), quatern_k(g));
291 void quatern_add(quatern res, quatern g1, quatern g2)
296 /* addition is defined point-wise */
297 bigz_add(quatern_z(accu), quatern_z(g1), quatern_z(g2));
298 bigz_add(quatern_i(accu), quatern_i(g1), quatern_i(g2));
299 bigz_add(quatern_j(accu), quatern_j(g1), quatern_j(g2));
300 bigz_add(quatern_k(accu), quatern_k(g1), quatern_k(g2));
302 quatern_set(res, accu);
306 void quatern_sub(quatern res, quatern g1, quatern g2)
311 /* subtraction is defined point-wise */
312 bigz_sub(quatern_z(accu), quatern_z(g1), quatern_z(g2));
313 bigz_sub(quatern_i(accu), quatern_i(g1), quatern_i(g2));
314 bigz_sub(quatern_j(accu), quatern_j(g1), quatern_j(g2));
315 bigz_sub(quatern_k(accu), quatern_k(g1), quatern_k(g2));
317 quatern_set(res, accu);
321 void quatern_mul(quatern res, quatern g1, quatern g2)
323 /* multiplication is defined as:
324 * (a + bi + cj + dk)*(e + fi + gj + hk) = <too complex ;)>
326 bigz accu1, accu2, accu3, accu4;
334 /* compute the integral part */
335 bigz_mul(accu1, quatern_z(g1), quatern_z(g2));
336 bigz_mul(accu2, quatern_i(g1), quatern_i(g2));
337 bigz_mul(accu3, quatern_j(g1), quatern_j(g2));
338 bigz_mul(accu4, quatern_k(g1), quatern_k(g2));
340 bigz_sub(accu1, accu1, accu2);
341 bigz_sub(accu1, accu1, accu3);
342 bigz_sub(accu1, accu1, accu4);
343 bigz_set(quatern_z(accu), accu1);
345 /* compute the i part */
346 bigz_mul(accu1, quatern_z(g1), quatern_i(g2));
347 bigz_mul(accu2, quatern_i(g1), quatern_z(g2));
348 bigz_mul(accu3, quatern_j(g1), quatern_k(g2));
349 bigz_mul(accu4, quatern_k(g1), quatern_j(g2));
351 bigz_add(accu1, accu1, accu2);
352 bigz_add(accu1, accu1, accu3);
353 bigz_sub(accu1, accu1, accu4);
354 bigz_set(quatern_i(accu), accu1);
356 /* compute the j part */
357 bigz_mul(accu1, quatern_z(g1), quatern_j(g2));
358 bigz_mul(accu2, quatern_i(g1), quatern_k(g2));
359 bigz_mul(accu3, quatern_j(g1), quatern_z(g2));
360 bigz_mul(accu4, quatern_k(g1), quatern_i(g2));
362 bigz_sub(accu1, accu1, accu2);
363 bigz_add(accu1, accu1, accu3);
364 bigz_add(accu1, accu1, accu4);
365 bigz_set(quatern_j(accu), accu1);
367 /* compute the k part */
368 bigz_mul(accu1, quatern_z(g1), quatern_k(g2));
369 bigz_mul(accu2, quatern_i(g1), quatern_j(g2));
370 bigz_mul(accu3, quatern_j(g1), quatern_i(g2));
371 bigz_mul(accu4, quatern_k(g1), quatern_z(g2));
373 bigz_add(accu1, accu1, accu2);
374 bigz_sub(accu1, accu1, accu3);
375 bigz_add(accu1, accu1, accu4);
376 bigz_set(quatern_k(accu), accu1);
378 quatern_set(res, accu);
387 void quatern_div(quatern res, quatern g1, quatern g2)
389 /* division is defined as:
390 * (a + bi + cj + dk) div (a'+b'i+c'j+d'k) =
391 * ((a+bi+cj+dk)*conj(a'+b'i+c'j+d'k)) div (a'^2 + b^2 + c^2 + d^2)
394 quatern_norm(ent_scratch_bigz, g2);
396 /* do normal multiplication with conjugate of g2 */
397 quatern_conj(ent_scratch_quatern, g2);
398 quatern_mul(res, g1, ent_scratch_quatern);
400 /* now divide (g1*conj(g2)) by |g2| (point-wise) */
401 bigz_div(quatern_z(res), quatern_z(res), ent_scratch_bigz);
402 bigz_div(quatern_i(res), quatern_i(res), ent_scratch_bigz);
403 bigz_div(quatern_j(res), quatern_j(res), ent_scratch_bigz);
404 bigz_div(quatern_k(res), quatern_k(res), ent_scratch_bigz);
407 void quatern_mod(quatern res, quatern g1, quatern g2)
410 /* the modulo relation is defined as:
411 * (a + bi) mod (c + di) ~
412 * (a+bi) - ((a+bi) div (c-di)) * (c+di)
417 /* do normal division */
418 quatern_div(accug, g1, g2);
420 /* now re-multiply g2 */
421 quatern_mul(accug, accug, g2);
423 /* and find the difference */
424 quatern_sub(res, g1, accug);
429 void quatern_pow(quatern res, quatern g1, unsigned long g2)
431 #if defined(HAVE_MPZ) && defined(WITH_GMP)
434 bigz bin, resintg, resimag, tmpbz1, tmpbz2, tmpbz3, intg, imag;
445 bigz_set_long(resintg, 0L);
446 bigz_set_long(resimag, 0L);
448 bigz_set(intg, quatern_z(g1));
449 bigz_set(imag, quatern_i(g1));
451 /* we compute using the binomial coefficients */
452 for (i=0; i<=g2; i++) {
453 mpz_bin_uiui(bin, g2, i);
455 /* real part changes */
456 bigz_pow(tmpbz1, intg, g2-i);
457 bigz_pow(tmpbz2, imag, i);
458 bigz_mul(tmpbz3, tmpbz1, tmpbz2);
459 bigz_mul(bin, bin, tmpbz3);
461 bigz_add(resintg, resintg, bin);
462 } else if (i % 4 == 2) {
463 bigz_sub(resintg, resintg, bin);
466 /* imag part changes */
467 bigz_pow(tmpbz1, intg, g2-i);
468 bigz_pow(tmpbz2, imag, i);
469 bigz_mul(tmpbz3, tmpbz1, tmpbz2);
470 bigz_mul(bin, bin, tmpbz3);
472 bigz_add(resimag, resimag, bin);
473 } else if (i % 4 == 3) {
474 bigz_sub(resimag, resimag, bin);
479 quatern_set_bigz_bigz_bigz_bigz(res, resintg, resimag, resimag, resimag);
490 quatern_set_long_long(res, 0L, 0L);
497 #define I_UNARY_SYMBOL 2
500 #define J_UNARY_SYMBOL 16
503 #define K_UNARY_SYMBOL 128
507 int isquatern_string (const char *cp)
510 const Bufbyte *ucp = (const Bufbyte *)cp;
513 /* parse the z-part */
515 if (*ucp == '+' || *ucp == '-')
518 if (*ucp >= '0' && *ucp <= '9') {
520 while (*ucp >= '0' && *ucp <= '9')
524 /* check if we had a int number until here */
525 if (!(state == (Z_INT)))
528 /* now parse i-part */
530 if (*ucp == '+' || *ucp == '-') {
531 state |= I_UNARY_SYMBOL;
535 if (*ucp >= '0' && *ucp <= '9') {
537 while (*ucp >= '0' && *ucp <= '9')
540 if (*ucp == 'i' || *ucp == 'I') {
544 /* check if we had a quatern number until here */
545 if (!(state == (I_UNARY_SYMBOL | I_INT | I_CHAR) ||
546 state == (I_UNARY_SYMBOL | I_CHAR)))
549 /* now parse j-part */
551 if (*ucp == '+' || *ucp == '-') {
552 state |= J_UNARY_SYMBOL;
556 if (*ucp >= '0' && *ucp <= '9') {
558 while (*ucp >= '0' && *ucp <= '9')
561 if (*ucp == 'j' || *ucp == 'J') {
565 /* check if we had a quatern number until here */
566 if (!(state == (J_UNARY_SYMBOL | J_INT | J_CHAR) ||
567 state == (J_UNARY_SYMBOL | J_CHAR)))
570 /* now parse k-part */
572 if (*ucp == '+' || *ucp == '-') {
573 state |= K_UNARY_SYMBOL;
577 if (*ucp >= '0' && *ucp <= '9') {
579 while (*ucp >= '0' && *ucp <= '9')
582 if (*ucp == 'k' || *ucp == 'K') {
586 /* check if we had a quatern number until here */
587 if (!(state == (K_UNARY_SYMBOL | K_INT | K_CHAR) ||
588 state == (K_UNARY_SYMBOL | K_CHAR)))
591 return (((*ucp == 0) || (*ucp == ' ') || (*ucp == '\t') ||
592 (*ucp == '\n') || (*ucp == '\r') || (*ucp == '\f')));
595 Lisp_Object read_quatern_string(char *cp)
597 bigz bz_z, bz_i, bz_j, bz_k;
608 /* MPZ bigz_set_string has no effect
609 * with initial + sign */
616 /* jump over a leading minus */
620 while ((*cp >= '0' && *cp <= '9'))
623 /* MPZ cannot read numbers with characters after them.
624 * See limitations below in convert GMP-MPZ strings
628 bigz_set_string(bz_z, (char *)end, 0);
631 /* read the i-part */
641 if ((*cp == 'i' || *cp == 'I') && (sign == 1)) {
642 /* expand +i to +1i */
643 bigz_set_long(bz_i, 1L);
644 } else if ((*cp == 'i' || *cp == 'I') && (sign == -1)) {
645 /* expand -i to -1i */
646 bigz_set_long(bz_i, -1L);
651 while ((*cp >= '0' && *cp <= '9'))
655 bigz_set_string(bz_i, (char *)end, 0);
659 if (*cp == 'i' || *cp == 'I')
662 /* read the j-part */
672 if ((*cp == 'j' || *cp == 'J') && (sign == 1)) {
673 /* expand +j to +1j */
674 bigz_set_long(bz_j, 1L);
675 } else if ((*cp == 'j' || *cp == 'J') && (sign == -1)) {
676 /* expand -j to -1j */
677 bigz_set_long(bz_j, -1L);
682 while ((*cp >= '0' && *cp <= '9'))
686 bigz_set_string(bz_j, (char *)end, 0);
690 if (*cp == 'j' || *cp == 'J')
693 /* read the k-part */
703 if ((*cp == 'k' || *cp == 'K') && (sign == 1)) {
704 /* expand +k to +1k */
705 bigz_set_long(bz_k, 1L);
706 } else if ((*cp == 'k' || *cp == 'K') && (sign == -1)) {
707 /* expand -k to -1k */
708 bigz_set_long(bz_k, -1L);
713 while ((*cp >= '0' && *cp <= '9'))
717 bigz_set_string(bz_k, (char *)end, 0);
721 if (*cp == 'k' || *cp == 'K')
724 result = make_quatern_bz(bz_z, bz_i, bz_j, bz_k);
735 ent_quatern_zerop(Lisp_Object o)
737 return (bigz_sign(quatern_z(XQUATERN_DATA(o))) == 0 &&
738 bigz_sign(quatern_i(XQUATERN_DATA(o))) == 0 &&
739 bigz_sign(quatern_j(XQUATERN_DATA(o))) == 0 &&
740 bigz_sign(quatern_k(XQUATERN_DATA(o))) == 0);
744 ent_quatern_onep(Lisp_Object o)
746 return ((bigz_fits_long_p(quatern_z(XQUATERN_DATA(o))) &&
747 bigz_to_long(quatern_z(XQUATERN_DATA(o))) == 1L) &&
748 bigz_sign(quatern_i(XQUATERN_DATA(o))) == 0 &&
749 bigz_sign(quatern_j(XQUATERN_DATA(o))) == 0 &&
750 bigz_sign(quatern_k(XQUATERN_DATA(o))) == 0);
754 ent_quatern_unitp(Lisp_Object o)
756 return (!ent_quatern_zerop(o) &&
757 (bigz_fits_long_p(quatern_z(XQUATERN_DATA(o))) &&
758 (bigz_to_long(quatern_z(XQUATERN_DATA(o))) == 0L ||
759 bigz_to_long(quatern_z(XQUATERN_DATA(o))) == 1L ||
760 bigz_to_long(quatern_z(XQUATERN_DATA(o))) == -1L)) &&
761 (bigz_fits_long_p(quatern_i(XQUATERN_DATA(o))) &&
762 (bigz_to_long(quatern_i(XQUATERN_DATA(o))) == 0L ||
763 bigz_to_long(quatern_i(XQUATERN_DATA(o))) == 1L ||
764 bigz_to_long(quatern_i(XQUATERN_DATA(o))) == -1L)) &&
765 (bigz_fits_long_p(quatern_j(XQUATERN_DATA(o))) &&
766 (bigz_to_long(quatern_j(XQUATERN_DATA(o))) == 0L ||
767 bigz_to_long(quatern_j(XQUATERN_DATA(o))) == 1L ||
768 bigz_to_long(quatern_j(XQUATERN_DATA(o))) == -1L)) &&
769 (bigz_fits_long_p(quatern_k(XQUATERN_DATA(o))) &&
770 (bigz_to_long(quatern_k(XQUATERN_DATA(o))) == 0L ||
771 bigz_to_long(quatern_k(XQUATERN_DATA(o))) == 1L ||
772 bigz_to_long(quatern_k(XQUATERN_DATA(o))) == -1L)));
775 static inline Lisp_Object
776 ent_sum_QUATERN_T(Lisp_Object l, Lisp_Object r)
778 quatern_add(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
779 return make_quatern_qu(ent_scratch_quatern);
781 static inline Lisp_Object
782 ent_sum_QUATERN_T_INT_T(Lisp_Object l, Lisp_Object r)
784 quatern_set_long(ent_scratch_quatern, ent_int(r));
785 quatern_add(ent_scratch_quatern, XQUATERN_DATA(l), ent_scratch_quatern);
786 return make_quatern_qu(ent_scratch_quatern);
788 static inline Lisp_Object
789 ent_sum_INT_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
791 quatern_set_long(ent_scratch_quatern, ent_int(l));
792 quatern_add(ent_scratch_quatern, ent_scratch_quatern, XQUATERN_DATA(r));
793 return make_quatern_qu(ent_scratch_quatern);
795 static inline Lisp_Object
796 ent_sum_QUATERN_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
798 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(r));
799 quatern_add(ent_scratch_quatern, XQUATERN_DATA(l), ent_scratch_quatern);
800 return make_quatern_qu(ent_scratch_quatern);
802 static inline Lisp_Object
803 ent_sum_BIGZ_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
805 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(l));
806 quatern_add(ent_scratch_quatern, ent_scratch_quatern, XQUATERN_DATA(r));
807 return make_quatern_qu(ent_scratch_quatern);
810 static inline Lisp_Object
811 ent_diff_QUATERN_T(Lisp_Object l, Lisp_Object r)
813 quatern_sub(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
814 return make_quatern_qu(ent_scratch_quatern);
816 static inline Lisp_Object
817 ent_diff_QUATERN_T_INT_T(Lisp_Object l, Lisp_Object r)
819 quatern_set_long(ent_scratch_quatern, ent_int(r));
820 quatern_sub(ent_scratch_quatern, XQUATERN_DATA(l), ent_scratch_quatern);
821 return make_quatern_qu(ent_scratch_quatern);
823 static inline Lisp_Object
824 ent_diff_INT_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
826 quatern_set_long(ent_scratch_quatern, ent_int(l));
827 quatern_sub(ent_scratch_quatern, ent_scratch_quatern, XQUATERN_DATA(r));
828 return make_quatern_qu(ent_scratch_quatern);
830 static inline Lisp_Object
831 ent_diff_QUATERN_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
833 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(r));
834 quatern_sub(ent_scratch_quatern, XQUATERN_DATA(l), ent_scratch_quatern);
835 return make_quatern_qu(ent_scratch_quatern);
837 static inline Lisp_Object
838 ent_diff_BIGZ_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
840 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(l));
841 quatern_sub(ent_scratch_quatern, ent_scratch_quatern, XQUATERN_DATA(r));
842 return make_quatern_qu(ent_scratch_quatern);
845 static inline Lisp_Object
846 ent_neg_QUATERN_T(Lisp_Object l)
848 quatern_neg(ent_scratch_quatern, XQUATERN_DATA(l));
849 return make_quatern_qu(ent_scratch_quatern);
851 static inline Lisp_Object
852 ent_prod_QUATERN_T(Lisp_Object l, Lisp_Object r)
854 quatern_mul(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
855 return make_quatern_qu(ent_scratch_quatern);
857 static inline Lisp_Object
858 ent_prod_QUATERN_T_INT_T(Lisp_Object l, Lisp_Object r)
860 quatern_set_long(ent_scratch_quatern, ent_int(r));
861 quatern_mul(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
862 return make_quatern_qu(ent_scratch_quatern);
864 static inline Lisp_Object
865 ent_prod_INT_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
867 quatern_set_long(ent_scratch_quatern, ent_int(l));
868 quatern_mul(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
869 return make_quatern_qu(ent_scratch_quatern);
871 static inline Lisp_Object
872 ent_prod_QUATERN_T_BIGZ_T(Lisp_Object l, Lisp_Object r)
874 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(r));
875 quatern_mul(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
876 return make_quatern_qu(ent_scratch_quatern);
878 static inline Lisp_Object
879 ent_prod_BIGZ_T_QUATERN_T(Lisp_Object l, Lisp_Object r)
881 quatern_set_bigz(ent_scratch_quatern, XBIGZ_DATA(l));
882 quatern_mul(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
883 return make_quatern_qu(ent_scratch_quatern);
886 static inline Lisp_Object
887 ent_div_QUATERN_T(Lisp_Object l, Lisp_Object r)
889 if (ent_quatern_zerop(r)) {
890 if (!ent_quatern_zerop(l)) {
891 return make_indef(COMPLEX_INFINITY);
893 return make_indef(NOT_A_NUMBER);
896 quatern_div(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
897 return make_quatern_qu(ent_scratch_quatern);
899 #if defined(HAVE_MPC) && 0
900 /* this does not work yet, our quaternions are the integral ring of the division
901 algebra usually known as quaternions
903 static inline Lisp_Object
904 ent_quo_QUATERN_T(Lisp_Object l, Lisp_Object r)
906 if (ent_quatern_zerop(r)) {
907 if (!ent_quatern_zerop(l)) {
908 return make_indef(COMPLEX_INFINITY);
910 return make_indef(NOT_A_NUMBER);
913 bigc_set_prec(ent_scratch_bigc, internal_get_precision(Qnil));
914 bigc_div(ent_scratch_bigc,
915 XBIGC_DATA(Fcoerce_number(l, Qbigc, Qnil)),
916 XBIGC_DATA(Fcoerce_number(r, Qbigc, Qnil)));
917 return make_bigc_bc(ent_scratch_bigc);
920 static inline Lisp_Object
921 ent_inv_QUATERN_T(Lisp_Object r)
923 if (ent_quatern_zerop(r)) {
924 return make_indef(COMPLEX_INFINITY);
926 quatern_set_long(ent_scratch_quatern, 1L);
927 quatern_div(ent_scratch_quatern, ent_scratch_quatern, XQUATERN_DATA(r));
928 return make_quatern_qu(ent_scratch_quatern);
930 static inline Lisp_Object
931 ent_rem_QUATERN_T(Lisp_Object l, Lisp_Object r)
933 if (ent_quatern_zerop(r)) {
934 return Qent_quatern_zero;
936 quatern_mod(ent_scratch_quatern, XQUATERN_DATA(l), XQUATERN_DATA(r));
937 return make_quatern_qu(ent_scratch_quatern);
939 static inline Lisp_Object
940 ent_pow_QUATERN_T_integer(Lisp_Object l, Lisp_Object r)
947 if (bigz_fits_ulong_p(XBIGZ_DATA(r)))
948 expo = bigz_to_ulong(XBIGZ_DATA(r));
950 Fsignal(Qarith_error, r);
952 Fsignal(Qdomain_error, r);
954 quatern_pow(ent_scratch_quatern, XQUATERN_DATA(l), expo);
955 return make_quatern_qu(ent_scratch_quatern);
960 ent_eq_quatern(Lisp_Object l, Lisp_Object r)
962 return (bigz_eql(quatern_z(XQUATERN_DATA(l)),
963 quatern_z(XQUATERN_DATA(r))) &&
964 bigz_eql(quatern_i(XQUATERN_DATA(l)),
965 quatern_i(XQUATERN_DATA(r))) &&
966 bigz_eql(quatern_j(XQUATERN_DATA(l)),
967 quatern_j(XQUATERN_DATA(r))) &&
968 bigz_eql(quatern_k(XQUATERN_DATA(l)),
969 quatern_k(XQUATERN_DATA(r))));
973 ent_ne_quatern(Lisp_Object l, Lisp_Object r)
975 return (bigz_eql(quatern_z(XQUATERN_DATA(l)),
976 quatern_z(XQUATERN_DATA(r))) &&
977 bigz_eql(quatern_i(XQUATERN_DATA(l)),
978 quatern_i(XQUATERN_DATA(r))) &&
979 bigz_eql(quatern_j(XQUATERN_DATA(l)),
980 quatern_j(XQUATERN_DATA(r))) &&
981 bigz_eql(quatern_k(XQUATERN_DATA(l)),
982 quatern_k(XQUATERN_DATA(r))));
986 static inline Lisp_Object
987 ent_vallt_QUATERN_T(Lisp_Object l, Lisp_Object r)
993 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(l));
994 quatern_norm(b2, XQUATERN_DATA(r));
995 result = bigz_lt(ent_scratch_bigz, b2);
998 return (result) ? Qt : Qnil;
1000 static inline Lisp_Object
1001 ent_valgt_QUATERN_T(Lisp_Object l, Lisp_Object r)
1007 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(l));
1008 quatern_norm(b2, XQUATERN_DATA(r));
1009 result = bigz_gt(ent_scratch_bigz, b2);
1012 return (result) ? Qt : Qnil;
1014 static inline Lisp_Object
1015 ent_valeq_QUATERN_T(Lisp_Object l, Lisp_Object r)
1021 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(l));
1022 quatern_norm(b2, XQUATERN_DATA(r));
1023 result = bigz_eql(ent_scratch_bigz, b2);
1026 return (result) ? Qt : Qnil;
1028 static inline Lisp_Object
1029 ent_valne_QUATERN_T(Lisp_Object l, Lisp_Object r)
1035 quatern_norm(ent_scratch_bigz, XQUATERN_DATA(l));
1036 quatern_norm(b2, XQUATERN_DATA(r));
1037 result = bigz_eql(ent_scratch_bigz, b2);
1040 return (result) ? Qnil : Qt;
1045 static inline Lisp_Object
1046 ent_lift_all_QUATERN_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1048 number = ent_lift(number, BIGZ_T, NULL);
1049 bigz_set_long(ent_scratch_bigz, 0L);
1050 return make_quatern_bz(XBIGZ_DATA(number),
1058 ent_lift_COMPLEX_QUATERN_T(Lisp_Object number, ent_lift_args_t SXE_UNUSED(la))
1062 z = Freal_part(number);
1063 i = Fimaginary_part(number);
1065 z = ent_lift(z, BIGZ_T, NULL);
1066 i = ent_lift(i, BIGZ_T, NULL);
1068 bigz_set_long(ent_scratch_bigz, 0L);
1069 return make_quatern_bz(XBIGZ_DATA(z), XBIGZ_DATA(i),
1077 ent_quatern_nullary_optable_init(void)
1079 Qent_quatern_zero = make_quatern(0L, 0L, 0L, 0L);
1080 Qent_quatern_one = make_quatern(1L, 0L, 0L, 0L);
1081 staticpro(&Qent_quatern_zero);
1082 staticpro(&Qent_quatern_one);
1084 ent_nullop_register(ASE_NULLARY_OP_ZERO, QUATERN_T, Qent_quatern_zero);
1085 ent_nullop_register(ASE_NULLARY_OP_ONE, QUATERN_T, Qent_quatern_one);
1089 ent_quatern_unary_optable_init(void)
1091 ent_unop_register(ASE_UNARY_OP_NEG, QUATERN_T, ent_neg_QUATERN_T);
1092 ent_unop_register(ASE_UNARY_OP_INV, QUATERN_T, ent_inv_QUATERN_T);
1096 ent_quatern_binary_optable_init(void)
1099 ent_binop_register(ASE_BINARY_OP_SUM,
1100 QUATERN_T, QUATERN_T, ent_sum_QUATERN_T);
1101 ent_binop_register(ASE_BINARY_OP_SUM,
1102 QUATERN_T, INT_T, ent_sum_QUATERN_T_INT_T);
1103 ent_binop_register(ASE_BINARY_OP_SUM,
1104 INT_T, QUATERN_T, ent_sum_INT_T_QUATERN_T);
1105 ent_binop_register(ASE_BINARY_OP_SUM,
1106 QUATERN_T, BIGZ_T, ent_sum_QUATERN_T_BIGZ_T);
1107 ent_binop_register(ASE_BINARY_OP_SUM,
1108 BIGZ_T, QUATERN_T, ent_sum_BIGZ_T_QUATERN_T);
1110 ent_binop_register(ASE_BINARY_OP_DIFF,
1111 QUATERN_T, QUATERN_T, ent_diff_QUATERN_T);
1112 ent_binop_register(ASE_BINARY_OP_DIFF,
1113 QUATERN_T, INT_T, ent_diff_QUATERN_T_INT_T);
1114 ent_binop_register(ASE_BINARY_OP_DIFF,
1115 INT_T, QUATERN_T, ent_diff_INT_T_QUATERN_T);
1116 ent_binop_register(ASE_BINARY_OP_DIFF,
1117 QUATERN_T, BIGZ_T, ent_diff_QUATERN_T_BIGZ_T);
1118 ent_binop_register(ASE_BINARY_OP_DIFF,
1119 BIGZ_T, QUATERN_T, ent_diff_BIGZ_T_QUATERN_T);
1121 ent_binop_register(ASE_BINARY_OP_PROD,
1122 QUATERN_T, QUATERN_T, ent_prod_QUATERN_T);
1123 ent_binop_register(ASE_BINARY_OP_PROD,
1124 QUATERN_T, INT_T, ent_prod_QUATERN_T_INT_T);
1125 ent_binop_register(ASE_BINARY_OP_PROD,
1126 INT_T, QUATERN_T, ent_prod_INT_T_QUATERN_T);
1127 ent_binop_register(ASE_BINARY_OP_PROD,
1128 QUATERN_T, BIGZ_T, ent_prod_QUATERN_T_BIGZ_T);
1129 ent_binop_register(ASE_BINARY_OP_PROD,
1130 BIGZ_T, QUATERN_T, ent_prod_BIGZ_T_QUATERN_T);
1132 /* divisions and quotients */
1133 ent_binop_register(ASE_BINARY_OP_DIV,
1134 QUATERN_T, QUATERN_T, ent_div_QUATERN_T);
1136 ent_binop_register(ASE_BINARY_OP_DIV,
1137 QUATERN_T, INT_T, ent_div_QUATERN_T_INT_T);
1138 ent_binop_register(ASE_BINARY_OP_DIV,
1139 INT_T, QUATERN_T, ent_div_INT_T_QUATERN_T);
1140 ent_binop_register(ASE_BINARY_OP_DIV,
1141 QUATERN_T, BIGZ_T, ent_div_QUATERN_T_BIGZ_T);
1142 ent_binop_register(ASE_BINARY_OP_DIV,
1143 BIGZ_T, QUATERN_T, ent_div_BIGZ_T_QUATERN_T);
1146 ent_binop_register(ASE_BINARY_OP_QUO,
1147 QUATERN_T, QUATERN_T, ent_div_QUATERN_T);
1149 ent_binop_register(ASE_BINARY_OP_QUO,
1150 QUATERN_T, INT_T, ent_quo_QUATERN_T_INT_T);
1151 ent_binop_register(ASE_BINARY_OP_QUO,
1152 INT_T, QUATERN_T, ent_quo_INT_T_QUATERN_T);
1153 ent_binop_register(ASE_BINARY_OP_DIV,
1154 QUATERN_T, BIGZ_T, ent_div_QUATERN_T_BIGZ_T);
1155 ent_binop_register(ASE_BINARY_OP_DIV,
1156 BIGZ_T, QUATERN_T, ent_div_BIGZ_T_QUATERN_T);
1159 #if 0 /* not implemented yet */
1160 ent_binop_register(ASE_BINARY_OP_REM,
1161 QUATERN_T, QUATERN_T, ent_rem_QUATERN_T);
1162 ent_binop_register(ASE_BINARY_OP_MOD,
1163 QUATERN_T, QUATERN_T, ent_rem_QUATERN_T);
1165 ent_binop_register(ASE_BINARY_OP_POW,
1166 QUATERN_T, INT_T, ent_pow_QUATERN_T_integer);
1167 ent_binop_register(ASE_BINARY_OP_POW,
1168 QUATERN_T, BIGZ_T, ent_pow_QUATERN_T_integer);
1173 ent_quatern_unary_reltable_init(void)
1175 ent_unrel_register(ASE_UNARY_REL_ZEROP, QUATERN_T, ent_quatern_zerop);
1176 ent_unrel_register(ASE_UNARY_REL_ONEP, QUATERN_T, ent_quatern_onep);
1177 ent_unrel_register(ASE_UNARY_REL_UNITP, QUATERN_T, ent_quatern_unitp);
1181 ent_quatern_binary_reltable_init(void)
1183 ent_binrel_register(ASE_BINARY_REL_EQUALP,
1184 QUATERN_T, QUATERN_T, ent_eq_quatern);
1185 ent_binrel_register(ASE_BINARY_REL_NEQP,
1186 QUATERN_T, QUATERN_T, ent_ne_quatern);
1190 ent_quatern_lifttable_init(void)
1192 ent_lift_register(INT_T, QUATERN_T, ent_lift_all_QUATERN_T);
1193 ent_lift_register(BIGZ_T, BIGC_T, ent_lift_all_QUATERN_T);
1195 ent_lift_register(BIGQ_T, QUATERN_T, ent_lift_all_QUATERN_T);
1198 ent_lift_register(BIGF_T, QUATERN_T, ent_lift_all_QUATERN_T);
1201 ent_lift_register(BIGFR_T, QUATERN_T, ent_lift_all_QUATERN_T);
1204 ent_lift_register(FLOAT_T, QUATERN_T, ent_lift_all_QUATERN_T);
1207 ent_lift_register(BIGG_T, QUATERN_T, ent_lift_COMPLEX_QUATERN_T);
1210 ent_lift_register(BIGC_T, QUATERN_T, ent_lift_COMPLEX_QUATERN_T);
1214 void init_optables_QUATERN_T(void)
1216 ent_quatern_nullary_optable_init();
1217 ent_quatern_unary_optable_init();
1218 ent_quatern_binary_optable_init();
1219 ent_quatern_unary_reltable_init();
1220 ent_quatern_binary_reltable_init();
1221 ent_quatern_lifttable_init();
1225 DEFUN ("make-quatern", Fmake_quatern, 4, 4, 0, /*
1226 Return the Quaternion whose z-component is Z,
1227 whose i-, j-, and k-components are I, J and K, respectively.
1231 Lisp_Object tmp_z, tmp_i, tmp_j, tmp_k;
1233 CHECK_COMPARABLE(z);
1234 CHECK_COMPARABLE(i);
1235 CHECK_COMPARABLE(j);
1236 CHECK_COMPARABLE(k);
1238 tmp_z = Fcoerce_number(z, Qbigz, Qnil);
1239 tmp_i = Fcoerce_number(i, Qbigz, Qnil);
1240 tmp_j = Fcoerce_number(j, Qbigz, Qnil);
1241 tmp_k = Fcoerce_number(k, Qbigz, Qnil);
1242 return make_quatern_bz(XBIGZ_DATA(tmp_z), XBIGZ_DATA(tmp_i),
1243 XBIGZ_DATA(tmp_j), XBIGZ_DATA(tmp_k));
1246 DEFUN ("quatern-z", Fquatern_z, 1, 1, 0, /*
1247 Return QUATERNION's z-component.
1251 CHECK_NUMBER(quaternion);
1253 if (COMPARABLEP(quaternion))
1255 else if (COMPLEXP(quaternion))
1256 return Freal_part(quaternion);
1257 else if (QUATERNP(quaternion))
1258 return make_bigz_bz(XQUATERN_Z(quaternion));
1260 return wrong_type_argument(Qquaternp, quaternion);
1262 DEFUN ("quatern-i", Fquatern_i, 1, 1, 0, /*
1263 Return QUATERNION's i-component.
1267 CHECK_NUMBER(quaternion);
1269 if (COMPARABLEP(quaternion))
1271 else if (COMPLEXP(quaternion))
1272 return Fimaginary_part(quaternion);
1273 else if (QUATERNP(quaternion))
1274 return make_bigz_bz(XQUATERN_I(quaternion));
1276 return wrong_type_argument(Qquaternp, quaternion);
1278 DEFUN ("quatern-j", Fquatern_j, 1, 1, 0, /*
1279 Return QUATERNION's j-component.
1283 CHECK_NUMBER(quaternion);
1285 if (COMPARABLEP(quaternion) || COMPLEXP(quaternion))
1287 else if (QUATERNP(quaternion))
1288 return make_bigz_bz(XQUATERN_J(quaternion));
1290 return wrong_type_argument(Qquaternp, quaternion);
1292 DEFUN ("quatern-k", Fquatern_k, 1, 1, 0, /*
1293 Return QUATERNION's k-component.
1297 CHECK_NUMBER(quaternion);
1299 if (COMPARABLEP(quaternion) || COMPLEXP(quaternion))
1301 else if (QUATERNP(quaternion))
1302 return make_bigz_bz(XQUATERN_K(quaternion));
1304 return wrong_type_argument(Qquaternp, quaternion);
1307 void init_ent_quatern(void)
1309 quatern_init(ent_scratch_quatern);
1312 void syms_of_ent_quatern(void)
1314 INIT_LRECORD_IMPLEMENTATION(quatern);
1316 DEFSYMBOL(Qquatern);
1318 DEFSUBR(Fmake_quatern);
1319 DEFSUBR(Fquatern_z);
1320 DEFSUBR(Fquatern_i);
1321 DEFSUBR(Fquatern_j);
1322 DEFSUBR(Fquatern_k);
1325 void vars_of_ent_quatern(void)
1327 Fprovide(intern("quatern"));