libera/#commonlisp - IRC Chatlog
Search
9:41:14
lukego
Hey I find myself wanting versions of the standard math functions (+, -, exp, sqrt, etc) that are specialized for all values being double-floats. So that I could depend on getting machine code doing efficient non-complex double float without worrying about type declarations on variables. did someone already make a wrapper arithmetic library like that?
10:08:14
lukego
pjb: I'm imagining something simpler e.g. just wrapper functions that wrap everything in COERCE or something.
10:13:44
Nilby
lukego: I'm fond of mass function generating macros for that. I've done something like it for standard string and sequence functions. I guess the hard part is making sure they get the fast path in disassemble.
10:16:11
White_Flame
not sure if it's easier to just macro up your local variable declarations, instead of the functions themselves
10:27:43
lukego
okay and maybe some tricks could be played with macrolet e.g. to make (. (+ (* ...) ...)) automagically coerced or something. hm.
10:28:12
Nilby
Yes. I love that kind of thing. And then you can even (loop for op in '(+ - * /) (def.wrapper ,s ...))
10:35:48
lukego
Using MACROLET to shadow + gives a package lock error on COMMON-LISP. That seems a bit harsh?
10:37:29
tfb
lukego: it's what the spec says (well, not package lock, but you're not allowed to do that
10:37:59
hayley
Would (INCF place) expanding to (SETF place (+ place 1)) [as a not-too-close approximation] still work?
10:40:51
tfb
(not related to previous) if *x* is special and has a toplevel binding, what should (progn (let ((*x* 3) (makunbound '*x*))) *x*) do?
11:32:27
Krystof
tfb: I believe it should return the toplevel binding of *x*. I'm not 100% convinced the language about that is airtight in the spec, though
11:39:24
tfb
Krystof: I think that too. The next question is what should (let ((*x* 3)) (makunbound '*x*) *x*) do?
11:40:10
tfb
because you seem to end up with a situation where a special variable is locally unbound but globally bound...
11:55:51
edgar-rft
(defvar *x* 123) (let ((*x* 1)) (makunbound '*x*) *x*) => error: variable *x* is unbound
12:05:36
beach
edgar-rft: With no DEFVAR, *X* would be lexical, so MAKUNBOUND has no effect on that lexical variable.
12:05:44
edgar-rft
_death: where is that "description from? the CLHS says nothing about "dynamic (special) variable", it says "symbol" instead
12:07:00
edgar-rft
beach: I assumed the same, but the CLHS doesn't say that MAKUNBOUND doesn't work on lexical symbols
12:07:30
_death
edgar-rft: this was written while the standard was written.. there is a follow-up by Moon explaining what is meant to happen
12:08:26
beach
edgar-rft: I see what you mean. That information is presumably taken for granted, but it would be good to include it in WSCL.
12:09:09
_death
Nilby: well, there is also a follow-up to Moon, where an attempt at disambiguation is mention in the context of Scheme
12:16:49
tfb
I assume it was abvious that MAKUNBOUND could not work on a lexical variable (it's a function for one thing!)
12:42:37
lukego
Coded up that idea of generating typed math wrappers: https://gist.github.com/lukego/726f23d20119c37d1bbd705a29f50f76. So e.g. defining |.| prefixed double-float ops and writing (.exp (.* -0.5d0 (.expt (./ (.- x μ) σ) 2))) knowing everything will be coerced safely to double and compiled to floating point machine code.
12:46:58
hayley
You might also want to consider inlining, in order to avoid boxing double-floats with current compilers.
12:47:23
_death
a similar idea is declared numerics (which don't coerce, just declare).. https://github.com/binghe/GBBopen/blob/master/source/tools/declared-numerics.lisp
13:01:05
lukego
hayley: current version is defining all the operators as macros so that should take care of the inlining angle, right?
13:03:43
lukego
(the whole idea here is to be a bit dumb i.e. for times when you want to be sure of how the compiled code will be but don't want to think too hard about your type declarations)
13:06:03
lukego
and maybe declarations are putting you on the path of getting runtime errors - or invalid results if safety is low - when type conversions might be more appropriate, especially on these fancy-pants wide-backended branch-predicting types of computers we're using these days
18:30:15
pve
Is one supposed to use (the double-float ...) or (coerce ... 'double-float) to tell the compiler what to expect?
18:34:43
mfiano
The former is a promise to the compiler, which is allowed to do nothing or anything.
18:35:05
lotuseater
hm i thought with THE it's more like a promise "this shall be that type" and with coerce an instruction "transforms this to the new type"
18:37:03
aeth
(the double-float x) is very, very, very close to (prog1 x (check-type x double-float))
18:38:03
aeth
SBCL doesn't. For DECLARE, DECLAIM, THE, etc., SBCL will use a faster CHECK-TYPE that is not recoverable.
18:39:31
aeth
What I mean is, (prog1 x (check-type x double-float)) in SBCL will let you supply a new x that satisfies double-float, while (the double-float x) will fail the program if it's not a double-float