This repository has been archived by the owner on May 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy patharithmetic-type.lisp
143 lines (124 loc) · 5.27 KB
/
arithmetic-type.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; Coding:utf-8 -*-
(in-package #:cl-num-utils)
(defun all-float-types ()
"Return a list of float types."
'(short-float single-float double-float long-float))
(defun available-float-type? (type)
"Return T iff type is available as a specialized array element type."
(equal type (upgraded-array-element-type type)))
(defun array-float-types ()
"Return a list of float types which are upgraded to themselves.
Consequences are undefined if modified."
(load-time-value
(remove-if (complement #'available-float-type?) (all-float-types))))
(defun array-float-and-complex-types ()
"Return a list of float types which are upgraded to themselves.
Consequences are undefined if modified."
(load-time-value
(remove-if (complement #'available-float-type?)
(append (all-float-types)
(mapcar (lambda (type) `(complex ,type))
(all-float-types))))
t))
(defun recognized-float-types ()
(let ((float '(short-float single-float double-float long-float)))
(concatenate 'vector float
(mapcar (curry #'list 'complex) float))))
(macrolet ((define% ()
`(defun float-type-index (type)
(cond
,@(let ((index 0))
(map 'list (lambda (type)
(prog1 `((subtypep type ',type) ,index)
(incf index)))
(recognized-float-types)))
(t nil)))))
(define%))
(defun float-contagion-matrix ()
(let ((indexes (ivec (length (recognized-float-types)))))
(outer* indexes indexes
(lambda (i1 i2)
))))
(defun float-contagion (&rest types)
(declare (optimize speed))
(let ((matrix (load-time-value
(let ((matrix (make-array '(8 8)
:element-type '(integer 0 7))))
(dotimes (i1 8)
(dotimes (i2 8)
(multiple-value-bind (c1 f1) (floor i1 4)
(multiple-value-bind (c2 f2) (floor i2 4)
(setf (aref matrix i1 i2)
(+ (max f1 f2) (* 4 (max c1 c2))))))))
matrix))))
(declare (type (simple-array (integer 0 7) (8 8)) matrix))
(if types
(aref #(short-float
single-float
double-float
long-float
(complex short-float)
(complex single-float)
(complex double-float)
(complex long-float))
(reduce (lambda (i1 i2) (aref matrix i1 i2)) types
:key (lambda (type)
(cond
((subtypep type 'short-float) 0)
((subtypep type 'single-float) 1)
((subtypep type 'double-float) 2)
((subtypep type 'long-float) 3)
((subtypep type '(complex short-float)) 4)
((subtypep type '(complex single-float)) 5)
((subtypep type '(complex double-float)) 6)
((subtypep type '(complex long-float)) 7)
(t (return-from float-contagion t))))))
nil)))
(defmacro define-float-contagion ()
)
(defun float-contagion (type1 type2)
(let+ (()
((&labels classify (type)
(cond
((subtypep type 'complex) (values (classify ())))
)
(typecase type
(complex )
(float ))
)
)))
)
(defmacro define-arithmetic-contagion (function float-types
&optional (docstring ""))
"Define (FUNCTION TYPES) which returns the result type applying float and
complex contagion rules to TYPES, considering FLOAT-TYPES and their complex
counterparts. For types outside these, T is returned."
(let+ (((&flet map-types (function)
(loop for type in float-types
for index from 0
collect (funcall function type index))))
((¯olet amap-types (form)
`(map-types (lambda (type index) ,form)))))
`(defun ,function (types)
,docstring
(declare (optimize speed))
(let ((complex? nil)
(float 0))
(declare (type fixnum float))
(loop for type in types do
(let+ (((&values f c?)
(cond
,@(amap-types `((subtypep type '(complex ,type))
(values ,index t)))
,@(amap-types `((subtypep type ',type) ,index))
(t (return-from ,function t)))))
(maxf float f)
(setf complex? (or complex? c?))))
(if complex?
(case float ,@(amap-types `(,index '(complex ,type))))
(case float ,@(amap-types `(,index ',type))))))))
(define-arithmetic-contagion array-arithmetic-contagion
#.(array-float-types)
"Return the upgraded element type of the arguments, applying rules of
float and complex contagion.")
(array-arithmetic-contagion '(double-float (complex single-float)))