1 ;;; xlib-math.el --- icky math things such as 4 byte ints, and int->string stuff.
3 ;; Copyright (C) 1996, 1997, 1998 Eric M. Ludlam
4 ;; Copyright (C) 2003-2005 XWEM Org.
6 ;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
7 ;; Modified: Zajcev Evgeny <zevlg@yandex.ru>
8 ;; Keywords: xlib, xwem
9 ;; X-RCS: $Id: xlib-math.el,v 1.8 2005-04-04 19:55:28 lg Exp $
11 ;; This file is part of XWEM.
13 ;; XWEM is free software; you can redistribute it and/or modify it
14 ;; under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
21 ;; License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 ;;; Synched up with: Not in FSF
31 ;; numbers->string string->numbers
33 ;; These routines are needed to convert numbers into strings which
34 ;; are passed over the network.
40 (defmacro Xtruncate (val)
41 "Do a safe truncate of VAL that might be larger than MAXINT."
42 `(truncate (if ,val (mod ,val 65536) 0)))
44 (defmacro XCharacter (val)
45 "Convert VAL (a float) into a truncated character value."
46 (if (fboundp 'int-to-char)
48 (list 'logand (list 'truncate (list 'mod val 65536)) 255))
49 (if (>= emacs-major-version 20)
50 (list 'logand (list 'truncate (list 'mod val 65536)) 255)
51 (list 'truncate (list 'mod val 65536)))))
53 (defmacro Xforcenum (val)
54 "Force VAL (a character) to be a number.
55 This macro forces XEmacs 20.3 to behave."
56 (if (fboundp 'char-to-int)
60 (defsubst int->string1 (num)
61 "Convert NUM into a 1 byte string in network order and return."
62 (char-to-string (XCharacter num)))
64 (defsubst string1->int (string)
65 "Convert STRING characters into an integer and return."
68 (defun int->string (num)
69 "Convert NUM into a 2 byte string in network order and return."
70 (setq num (truncate num))
71 (let ((l (logand num 255)) ;top byte
72 (h (ash (mod num 65536) -8))) ;upper byte
73 (concat (char-to-string l) (char-to-string h))))
75 (defalias 'int->string2 'int->string)
77 (defun string->int (string)
78 "Convert STRING 1st two characters into an integer and return."
79 (let ((l (aref string 0))
80 (h (if (> (length string) 1) (aref string 1) 0)))
83 (defun int->string4 (num)
84 "Convert NUM (a float or int) into a 4 byte network order string."
86 ;; if it isn't a float, then do int things
87 (concat (int->string num) (int->string 0)) ;0 upper part
89 ; (error "4 byte number is negative during conversion."))
90 (let ((tmp (float num))
92 ;; We only need to truncate the first part. After the first
93 ;; 8 bit shift, the number is small enought that a regular
95 (setq ts (concat ts (char-to-string (XCharacter tmp))))
96 (setq tmp (/ tmp (float 256)))
97 (setq ts (concat ts (char-to-string (XCharacter tmp))))
98 (setq tmp (/ tmp (float 256)))
99 (setq ts (concat ts (char-to-string (XCharacter tmp))))
100 (setq tmp (/ tmp (float 256)))
101 (setq ts (concat ts (char-to-string (XCharacter tmp)))))))
103 (defun string4->int (string)
104 "Convert STRING 1st four characters into a float and return."
105 ;; do nothing yet until we know what we need to do.
106 (+ (float (Xforcenum (aref string 0)))
107 (* (float (Xforcenum (aref string 1))) 256)
108 (* (float (Xforcenum (aref string 2))) 256 256)
109 (* (float (Xforcenum (aref string 3))) 256 256 256)))
111 (defun string2->number (string)
112 "Convert 2 first bytes in STRING to number."
113 (string->int string))
115 (defun string4->number (string)
116 "Convert 4 first bytes in STRING to number.
117 NOTE: Use `string4->int' when overflow may occur."
118 (+ (Xforcenum (aref string 0))
119 (lsh (Xforcenum (aref string 1)) 8)
120 (lsh (Xforcenum (aref string 2)) 16)
121 (lsh (Xforcenum (aref string 3)) 24)))
123 (defun int->string3 (num)
124 "Convert 3 first bytes in STRING to integer."
125 (string (logand num 255)
126 (logand (lsh num -8) 255)
127 (logand (lsh num -16) 255)))
130 (defun string->card8 (str)
131 (Xforcenum (aref str 0)))
133 (defun string->card16 (str)
134 (+ (Xforcenum (aref str 0))
135 (lsh (Xforcenum (aref str 1)) 8)))
137 (defun string->card32 (str)
138 (+ (Xforcenum (aref str 0))
139 (lsh (Xforcenum (aref str 1)) 8)
140 (lsh (Xforcenum (aref str 2)) 16)
141 (lsh (Xforcenum (aref str 3)) 24)))
143 (defun string->int8 (str)
144 (let ((v (Xforcenum (aref str 0))))
145 (funcall (if (> v #x7f) '- '+) (logand v #x7f))))
147 (defun string->int16 (str)
148 (let ((v (Xforcenum (aref str 1))))
149 (funcall (if (> v #x7f) '- '+)
150 (+ (Xforcenum (aref str 0))
151 (lsh (logand v #x7f) 8)))))
153 (defun string->int32 (str)
154 (let ((v (Xforcenum (aref str 3))))
155 (funcall (if (> v #x7f) '- '+)
156 (+ (Xforcenum (aref str 0))
157 (lsh (Xforcenum (aref str 1)) 8)
158 (lsh (Xforcenum (aref str 2)) 16)
159 (lsh (logand v #x7f) 24)))))
163 (defun card8->string (card8)
166 (defun card16->string (card16)
169 (defun card32->string (card32)
172 (defun int8->string (int8)
175 (defun int16->string (int16)
178 (defun int32->string (int32)
181 (defun X-pad (number)
182 "Return a number which is the padding for an X message of length NUMBER."
183 (% (- 4 (% number 4)) 4))
185 (defun X-padlen (string)
186 "Return a number which is length of STRING / 4.
187 If string is not divisible by 4, return string/4 + 1"
188 (if (= (% (length string) 4) 0)
189 (/ (length string) 4)
190 (+ (/ (length string) 4) 1)))
194 ;; These routines are needed to handle the 4 byte masks used in X.
195 ;; We won't implement the whole set, just the functionality we need
196 ;; to make the checks we want.
199 "Create a mask with a bit set in position POS.
200 This routine will not work for position 32 and up because we sim
203 (float (lsh 1 pos)) ;put in first byte
204 (setq pos (- pos 16)) ;divide pos by 16
205 (* (float (lsh 1 pos)) (float 65536)) ;push into high byte
208 (defun Xmask-and (val &rest args)
209 "Logically `and' VAL and MASK together.
210 They are floats to be broken down into two two byte ints.
211 MASK is stored in ARGS which is a list of *fill in when I remember*"
213 (let ((mask (car args)))
214 (setq args (cdr args))
215 (let ((lv (logand (Xtruncate val) 65535))
216 (hv (Xtruncate (/ val (float 65536))))
217 (lm (logand (Xtruncate mask) 65535))
218 (hm (Xtruncate (/ mask (float 65536)))))
219 (setq val (+ (float (logand lv lm))
220 (* (float (logand hv hm)) 65536))))))
223 (defun Xmask-or (val &rest args)
224 "Logically or VAL and MASK together.
225 They are floats to be broken down into two two byte ints.
226 MASK is stored in ARGS which is a list of *fill in when I remember*"
228 (let ((mask (car args)))
229 (setq args (cdr args))
230 (let ((lv (logand (Xtruncate val) 65535))
231 (hv (Xtruncate (/ val (float 65536))))
232 (lm (logand (Xtruncate mask) 65535))
233 (hm (Xtruncate (/ mask (float 65536)))))
234 (setq val (+ (float (logior lv lm))
235 (* (float (logior hv hm)) 65536))))))
238 (defun Xtest (val flag)
239 "Test value of bytes VAL for presence of FLAG.
240 Return t if it exists, nil otherwise."
241 (if (= (Xmask-and val flag) 0) nil t))
243 ;;; BITWISE routines:
245 ;; These routines are used to do other things to bits, necessary for
246 ;; calculating out new resource IDs for objects.
249 (defun Xcount-bits-int (mask)
250 "Count the number of bits in a given integer (16 bit) MASK."
253 (if (Xtest mask 1) (setq ret (1+ ret)))
254 (setq mask (ash mask -1)))
257 (defun Xmask-count (mask)
258 "Count the number of bits set in the mask MASK.
259 This is needed to identify new objects (client-selectable) thingies."
260 (let ((lv (Xtruncate mask))
261 (hv (Xtruncate (/ mask (float 65536)))))
262 (+ (Xcount-bits-int lv) (Xcount-bits-int hv))))
264 (defun Xmask-int-string (mask)
265 "Convert MASK as an integer into a string of 0s and 1s."
269 (setq s (concat s (if (= (logand mask (lsh 1 cnt)) 0) "0" "1")))
273 (defun Xmask-string (mask)
274 "Convert MASK into a string of 0s and 1s."
275 (let ((lv (Xtruncate mask))
276 (hv (Xtruncate (/ mask (float 65536)))))
277 (concat (Xmask-int-string hv) (Xmask-int-string lv))))
279 (defun Xmask-int-hex-string (mask &optional fill)
280 "Convert the integer MASK into a full hexidecimal number.
281 Optional argument FILL means to add 0s as necessary."
282 (let ((s (format "%x" mask)))
283 (if fill (substring (concat "0000" s) (length s)) s)))
285 (defun Xmask-hex-string (mask)
286 "Convert MASK into a hexidecimal string."
287 (let ((lv (Xtruncate mask))
288 (hv (Xtruncate (/ mask (float 65536)))))
290 (Xmask-int-hex-string hv)
291 (Xmask-int-hex-string lv (/= hv 0)))))
296 ;;; xmath.el ends here