Yesterday I tried to figure out the size of the new Mersenne Prime (http://www.mersenne.org/primes/?press=M74207281)
on my SBCL box (v. 1.3.2 (x64), Windows 10, Dell Core i5 8GB RAM)
After almost one hour I gave up and interrupted the calculation.
Below the resulting screen:
This is SBCL 1.3.2, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
WARNING: the Windows port is fragile, particularly for multithreaded
code. Unfortunately, the development team currently lacks the time
and resources this platform demands.
* (- (expt 2 74207281) 1)
debugger invoked on a SB-SYS:INTERACTIVE-INTERRUPT in thread
'#<THREAD "main thread" RUNNING {1002A9BD03}>:'
Interactive interrupt at #x100008BD9E.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE] Return from SB-WIN32::SIGINT.
1: [ABORT ] Exit debugger, returning to top level.
1
(SB-BIGNUM:MULTIPLY-BIGNUMS #<unavailable argument> #<unavailable argument>)
0] 1
To me this was interesting, because I tried the same expression on Racket 6.4, on the same machine,
And it took (comparatively) only 1m08s to start spitting numbers.
In Haskell, again on the same machine, with
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Prelude> 2^74207281 - 1
it took only 8s to start the numbers' exhibition.
Despite the fact that it could be a bug, do anyone know how SBCL do bignum multiplication? Would its way of doing it be the possible cause of delay?
Thanks in advance!
*EDIT
After Sylvester´s comment, maybe the right question is: What is preventing the big number from been shown? Yes, it is really big (Racket and Haskell versions wrote it to a text file of 21 MB), but it seems that there is something more than its size preventing the task´s completion.
The actual calculation is pretty fast on my machine, less than a second in fact.
(defun make-prime ()
(declare (optimize (safety 0)(debug 0)(speed 3)))
(time (- (expt 2 74207281) 1)))
(defparameter *prime* (make-prime))
;Evaluation took:
; 0.000 seconds of real time
; 0.000017 seconds of total run time (0.000015 user, 0.000002 system)
; 100.00% CPU
; 1,292 processor cycles
; 0 bytes consed
; ==> *PRIME*
However printing the number is a whole other matter.
Related
All of the resources online I find are for Common Lisp, even when I try to search specifically for original LISP resources. I suspect that Common is probably a lot easier, but I thought it might be fun to try Lisp out from the beginning of it's history as a language.
Yes, and it's easy in fact. This person has a tarball which lets you run Lisp 1.5 on the SIMH emulator for the IBM 7094, which must have, I think, been the system Lisp 1.5 was ported to from the 704 (the 7094 is a transistor machine, the 704 was valve (tube)). Here is a link to the slides from a talk given by Norman Richards at the March 2015 Clojure meetup where he must have demonstrated all this working.
Example
I did this on a scratch Ubuntu 20.04 machine.
Get SIMH, with aptitude install simh or whatever you are using.
Get the above tarball and unpack it.
unpack the utils-1.1.8.tar.gz tarball inside it and build txt2bcd;
put txt2bcd somewhere in your PATH;
profit.
The tarball includes a factorial program, inevitably, and here's a transcript of it running:
ts$ i7094 lisptape.ini factorial.txt
IBM 7094 simulator V3.8-1
MTA: unit is read only
MTA: unit is read only
LPT: creating new file
HALT instruction, PC: 10524 (TRA 10523)
Goodbye
ts$ cat sys.log
TEST FACTORIAL
THE TIME ( 0/ 0 000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS ..... -LEWIS CARROLL-
EVALQUOTE OPERATOR AS OF 1 MARCH 1961. INPUT LISTS NOW BEING READ.
THE TIME ( 0/ 0 000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS ..... -LEWIS CARROLL-
FUNCTION EVALQUOTE HAS BEEN ENTERED, ARGUMENTS..
DEFINE
(((FACTORIAL (LAMBDA (X) (COND ((EQUAL X 0) 1) (T (TIMES X (FACTORIAL (
SUB1 X)))))))))
END OF EVALQUOTE, VALUE IS ..
*TRUE*
FUNCTION EVALQUOTE HAS BEEN ENTERED, ARGUMENTS..
FACTORIAL
(10)
END OF EVALQUOTE, VALUE IS ..
3628800
THE TIME ( 0/ 0 000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS ..... -LEWIS CARROLL-
END OF EVALQUOTE OPERATOR
FIN END OF LISP RUN
So it's that easy: I was amazed, having spent much longer than this trying to get MACLISP to run. I think later systems are harder because they assume terminal types and so on as there is more interactivity.
Some other links
Some other links which might be useful (some from my original comment):
a listing of Lisp 1.5 for (I presume) the IBM 7094);
an IBM 704 emulator for Windows if you wanted to go even further back;
The SIMH software kits list lists Lisp for the PDP-1, which is what is described here and which is also very early.
Common Lisp provide a time macro for finding out how long a form takes to execute, and it prints the information to the trace output:
time evaluates form in the current environment (lexical and dynamic). … time prints various timing data and other information to trace output.
The nature and format of the printed information is
implementation-defined. Implementations are encouraged to provide such
information as elapsed real time, machine run time, and storage
management statistics.
For instance:
(time (length (make-array 1000000)))
Real time: 0.0140014 sec.
Run time: 0.0 sec.
Space: 4000008 Bytes
GC: 1, GC time: 0.0 sec.
Is there a way to collect these parameters and push them step by step into some stack or list and return it from a function?
Some things are standard: get-internal-run-time and get-internal-real-time:
(defvar *my-timings* nil)
(let ((run (get-internal-run-time))
(real (get-internal-real-time)))
(multiple-value-prog1 (my-code)
(push (cons (- (get-internal-run-time) run)
(- (get-internal-real-time) real))
*my-timings*)))
Others are not (space and GC count), you need to find the implementation-specific versions.
You might also consider using with-timing - it provides progress reports including ETA.
Incidentally, in your code, memory allocation (make-array) dwarfs length (which is slot access for an array).
I am learning ASDF but encountered strange issue when do loading the defined system. Here are some information.
i defined a .asd file named "hello.asd" with a single line content:
(asdf:defsystem :hellosystem)
and i put this file into a directory called "/tmp/pkg". After that, i run SBCL and try to load it. Here is the output:
This is SBCL 1.1.12, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (asdf:asdf-version)
"3.0.2"
* (push #P"/tmp/pkg/" asdf:*central-registry*)
(#P"/tmp/pkg/" #P"/Users/wuli2/quicklisp/quicklisp/")
* (asdf:load-system :hellosystem)
debugger invoked on a ASDF/FIND-SYSTEM:MISSING-COMPONENT:
Component :HELLOSYSTEM not found
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
((:METHOD ASDF/OPERATE:OPERATE (SYMBOL T)) ASDF/LISP-ACTION:LOAD-OP :HELLOSYSTEM) [fast-method]
0] 0
* (asdf:load-system :hello)
debugger invoked on a ASDF/FIND-SYSTEM:MISSING-COMPONENT:
Component :HELLO not found
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
((:METHOD ASDF/OPERATE:OPERATE (SYMBOL T)) ASDF/LISP-ACTION:LOAD-OP :HELLO) [fast-method]
0] 0
* (asdf:load-system :hellosystem)
T
*
Please be noted, the first time i tried to load system :hellosystem, it failed. So i load the system :hello, i gussed maybe it need a filename, it failed again. The weired thing happened when i occasionally run load system :hellosystem again, it worked.
So i made another test, change the file name to let it same as system name. Then run asdf:load-system, it worked directly.
It confused me very much, i cannot find any clue in ASDF manual that the two names should be identical?
Could somebody give me some insight on it?
Thanks,
Wu
I found this clue: "Note the name of a system is specified as a string or a symbol, typically a keyword. If a symbol (including a keyword), its name is taken and lowercased. The name must be a suitable value for the :name initarg to make-pathname in whatever filesystem the system is to be found."
http://common-lisp.net/project/asdf/asdf/Using-ASDF.html
The message is that an (asdf:defsystem <symbol> ...) form should reside in a file called <lowercased-symbol>.asd. If you name the system with a string, the file name should use that string.
Scheme newbie question-
Is there a way for me to reset my current REPL environment (i.e. the default user environment) without quitting and restarting my REPL? Basically I'd like a way to wipe out my current environment so that none of my previous defines are in effect. This is using GNU/MIT Scheme.
If this is impossible, what's the best practice here when just messing around with code in the REPL? I've heard people talk about creating and deleting packages, but most examples seem to be for Common Lisp which is a bit different.
I did find information on how to do this in the Clojure REPL but there were caveats and it seems like it's Clojure-specific: Can I clean the repl?
Thanks!
Edit: I'm able to accomplish functionally the same thing by quitting and restarting the REPL process itself. I found a way to do this but keep the connection to my editor (vim) alive using vim-screen. This is an acceptable solution if there's no way to do it from within the REPL. However, I'll keep the question open a bit longer to see if there's a way to do this inside the language as I think it will be instructive.
I think that this is implementation specific, but in MIT Scheme you can clear the REPL environment with:
1 ]=> (ge (make-top-level-environment))
The function (ge [environment]) "Changes the current REP loop environment to [environment]." and the function make-top-level-environment "returns a newly allocated top-level environment".
MIT Scheme has a bunch of environment-management functions that you can peruse here
I tested this on Mac OS X (10.6.7) with MIT Scheme 9.0.1 installed via the pre-built binary from the GNU site, with the following REPL session:
1 ]=> (define foo 1)
;Value: foo
1 ]=> foo
;Value: 1
1 ]=> (ge (make-top-level-environment))
;Value 13: #[environment 13]
1 ]=> foo
;Unbound variable: foo
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of foo.
; (RESTART 2) => Define foo to a given value.
; (RESTART 1) => Return to read-eval-print level 1.
2 error>
I think that different implementations have different conventions but I don't think there's anything quite like Common Lisp's packages. If you're not wedded to MIT Scheme, you should check out Racket and Dr Racket, which is a nice IDE that might be more powerful than a plain REPL at the command line, and I think it has some kind of module system. Racket is its own dialect of Scheme, so depending on what you're doing, it might not be appropriate. (the default language module in Racket is not the same as MIT Scheme)
I've struggled with all this recently (past few months) when I went looking for a Scheme that could run the code from Lisp in Small Pieces, which has a bunch of weird macros. Gambit ended up being the best bet. If you don't have a need like this though, check out Racket.
this is what I get when I try to do some calculations in emacs lisp...
(+ 2082844800. 1274511600.0)
=> 1209872752.0
(+ 2082844800.0 1274511600.0)
=> 3357356400.0
Could anyone tell me what's going on and what's the difference between representing a floating-point number with . and .0 at the end? Thanks
Building on Anton's answer and jamessan's answer, and reading the latest NEWS file:
It looks like you've got a 32-bit build of Emacs. Emacs has a limit for integers that is most-positive-fixnum, which has traditionally been 268435455 for 32-bit builds. In the latest Emacs (23.2), the NEWS file indicates:
** The Lisp reader turns integers that are too large/small into floats. For
instance, on machines where
536870911' is the largest integer,
reading536870912' gives the
floating-point object `536870912.0'.
This change only concerns the Lisp
reader; it does not affect how actual
integer objects overflow.
So, in 23.1 and earlier (on a 32-bit Emacs), 2082844800. was read as an integer, but is too big, causing it to overflow and turn into -64638848.
Adding the .0 suffix in 23.1 forced the lisp reader to treat the number as floating point, causing the math to turn out as you expect.
In Emacs 23.2, the reader does this conversion from integer to float for you automatically if the number is too large. So if you upgrade, you won't have to worry about this.
Try
(floatp 2082844800.)
(floatp 2082844800.0)
(integerp 2082844800.)
also
(+ 0 2082844800.)
Hope that helps
Using Emacs 23.2, I see no difference between the two expressions. Which version are you using and how are you performing the calculations?
It depends on what the largest integer value your build of Emacs can represent. Anything above that is promoted from an integer to a float. You can access this information through the most-positive-fixnum/most-negative-fixnum variables. In my case, most-positive-fixnum is 536870911 which is smaller than the 2082844800 and therefore explains why both expressions were the same for me.