mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-24 12:35:05 +02:00
Merge pull request #175 from kozross/master
Documentation for new SRFIs, some small code changes
This commit is contained in:
commit
21f54914b5
8 changed files with 835 additions and 31 deletions
|
@ -32,19 +32,22 @@ This section of the Cyclone API is based on the [R<sup>7</sup>RS Scheme Specific
|
||||||
|
|
||||||
Cyclone supports the following [Scheme Requests for Implementation (SRFI)](http://srfi.schemers.org/) libraries. Detailed information is available in the linked SRFI page as well as the provided Cyclone API:
|
Cyclone supports the following [Scheme Requests for Implementation (SRFI)](http://srfi.schemers.org/) libraries. Detailed information is available in the linked SRFI page as well as the provided Cyclone API:
|
||||||
|
|
||||||
- [`srfi 1`](api/srfi/1.md) - [List Library](http://srfi.schemers.org/srfi-1/srfi-1.html)
|
- [`srfi 1`](api/srfi/1.md) - [List library](http://srfi.schemers.org/srfi-1/srfi-1.html)
|
||||||
- [`srfi 2`](api/srfi/2.md) - [`and-let*`](http://srfi.schemers.org/srfi-2/srfi-2.html)
|
- [`srfi 2`](api/srfi/2.md) - [`and-let*`](http://srfi.schemers.org/srfi-2/srfi-2.html)
|
||||||
- [`srfi 8`](api/srfi/8.md) - [`receive`: Binding to multiple values](http://srfi.schemers.org/srfi-8/srfi-8.html) - Included as part of `scheme base`.
|
- [`srfi 8`](api/srfi/8.md) - [`receive`: Binding to multiple values](http://srfi.schemers.org/srfi-8/srfi-8.html) - Included as part of `scheme base`.
|
||||||
- [`srfi 18`](api/srfi/18.md) - [Multithreading support](http://srfi.schemers.org/srfi-18/srfi-18.html)
|
- [`srfi 18`](api/srfi/18.md) - [Multithreading support](http://srfi.schemers.org/srfi-18/srfi-18.html)
|
||||||
- [`srfi 27`](api/srfi/27.md) - [Sources of random bits](http://srfi.schemers.org/srfi-27/srfi-27.html)
|
- [`srfi 27`](api/srfi/27.md) - [Sources of random bits](http://srfi.schemers.org/srfi-27/srfi-27.html)
|
||||||
|
- [`srfi 28`](api/srfi/28.md) - [Basic format strings](http://srfi.schemers.org/srfi-28/srfi-28.html)
|
||||||
|
- [`srfi 60`](api/srfi/60.md) - [Integers as bits](http://srfi.schemers.org/srfi-60/srfi-60.html)
|
||||||
- [`srfi 69`](api/srfi/69.md) - [Basic hash tables](http://srfi.schemers.org/srfi-69/srfi-69.html)
|
- [`srfi 69`](api/srfi/69.md) - [Basic hash tables](http://srfi.schemers.org/srfi-69/srfi-69.html)
|
||||||
- [`srfi 106`](api/srfi/106.md) - [Basic socket interface](http://srfi.schemers.org/srfi-106/srfi-106.html)
|
- [`srfi 106`](api/srfi/106.md) - [Basic socket interface](http://srfi.schemers.org/srfi-106/srfi-106.html)
|
||||||
- [`srfi 111`](api/srfi/111.md) - [Boxes](http://srfi.schemers.org/srfi-111/srfi-111.html)
|
- [`srfi 111`](api/srfi/111.md) - [Boxes](http://srfi.schemers.org/srfi-111/srfi-111.html)
|
||||||
- [`srfi 113`](api/srfi/113.md) - [Sets and bags](http://srfi.schemers.org/srfi-113/srfi-113.html)
|
- [`srfi 113`](api/srfi/113.md) - [Sets and bags](http://srfi.schemers.org/srfi-113/srfi-113.html)
|
||||||
- [`srfi 117`](api/srfi/117.md) - [Mutable queues](http://srfi.schemers.org/srfi-117/srfi-117.html)
|
- [`srfi 117`](api/srfi/117.md) - [Mutable queues](http://srfi.schemers.org/srfi-117/srfi-117.html)
|
||||||
|
- [`srfi 121`](api/srfi/121.md) - [Generators](http://srfi.schemers.org/srfi-121/srfi-121.html)
|
||||||
- [`srfi 128`](api/srfi/128.md) - [Comparators](http://srfi.schemers.org/srfi-128/srfi-128.html)
|
- [`srfi 128`](api/srfi/128.md) - [Comparators](http://srfi.schemers.org/srfi-128/srfi-128.html)
|
||||||
- [`srfi 132`](api/srfi/132.md) - [Sort Libraries](http://srfi.schemers.org/srfi-132/srfi-132.html)
|
- [`srfi 132`](api/srfi/132.md) - [Sort libraries](http://srfi.schemers.org/srfi-132/srfi-132.html)
|
||||||
- [`srfi 133`](api/srfi/133.md) - [Vector Library (R7RS-compatible)](http://srfi.schemers.org/srfi-133/srfi-133.html)
|
- [`srfi 133`](api/srfi/133.md) - [Vector library (R7RS-compatible)](http://srfi.schemers.org/srfi-133/srfi-133.html)
|
||||||
|
|
||||||
# Cyclone Libraries
|
# Cyclone Libraries
|
||||||
|
|
||||||
|
|
458
docs/api/srfi/121.md
Normal file
458
docs/api/srfi/121.md
Normal file
|
@ -0,0 +1,458 @@
|
||||||
|
# SRFI 121 - Generators
|
||||||
|
|
||||||
|
Defines utility procedures that create, transform and consume generators. A
|
||||||
|
'generator' is a procedure with no arguments (a 'thunk') that works as a source
|
||||||
|
of values. Every time a generator is called, it yields a value.
|
||||||
|
|
||||||
|
Generators may be finite or infinite; a finite generator returns an end-of-file
|
||||||
|
object to indicate that it is exhausted (has no more values to give). For
|
||||||
|
example, ``read-char``, ``read-line`` and ``read`` are generators that produce
|
||||||
|
characters, lines and objects from the current input port.
|
||||||
|
|
||||||
|
This library is designed to provide lightweight laziness.
|
||||||
|
|
||||||
|
See the [SRFI document][1] for more information.
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
Generators can be divided into two classes: *finite* and *infinite*. Both kinds
|
||||||
|
of generator can be invoked an indefinite number of times. After a finite
|
||||||
|
generator has produced all of its values, it will return an end-of-file object
|
||||||
|
for all subsequent calls. A generator is said to be *exhausted* if calling it
|
||||||
|
will return an end-of-file object. By definition, an infinite generator can
|
||||||
|
never be exhausted.
|
||||||
|
|
||||||
|
A generator is said to be in an *undefined state* if it cannot be determined how
|
||||||
|
many values it has produced. This arises because it is impossible to tell by
|
||||||
|
inspection whether a generator is exhausted or not. For example,
|
||||||
|
``(generator-fold + 0 (generator 1 2 3) (generator 1 2))`` will compute 0 + 1 +
|
||||||
|
1 + 2 + 2 = 6, at which time the second generator will be exhausted. If the
|
||||||
|
first generator is invoked, however, it may return either 3 or an end-of-file
|
||||||
|
object, depending on whether the implementation of ``generator-fold`` invoked it
|
||||||
|
or not. Therefore, the first generator is said to be in an undefined state.
|
||||||
|
|
||||||
|
Functions provided under [generator operations](#generator-operations) do not
|
||||||
|
consume elements from their input generators. In general, they produce finite
|
||||||
|
generators if their inputs are finite.
|
||||||
|
|
||||||
|
Functions provided udner [consuming generated
|
||||||
|
values](#consuming-generated-values) consume all values from any generator
|
||||||
|
passed to them, and will not return if any of their arguments are infinite.
|
||||||
|
|
||||||
|
## Generator constructors
|
||||||
|
[`generator`](#generator)
|
||||||
|
[`make-iota-generator`](#make-iota-generator)
|
||||||
|
[`make-range-generator`](#make-range-generator)
|
||||||
|
[`make-coroutine-generator`](#make-coroutine-generator)
|
||||||
|
[`list->generator'](#list-generator)
|
||||||
|
[`vector->generator'](#vector-generator)
|
||||||
|
[`reverse-vector->generator'](#reverse-vector-generator)
|
||||||
|
[`string->generator`](#string-generator)
|
||||||
|
[`bytevector->generator`](#bytevector-generator)
|
||||||
|
[`make-for-each-generator`](#make-for-each-generator)
|
||||||
|
[`make-unfold-generator`](#make-unfold-generator)
|
||||||
|
|
||||||
|
## Generator operations
|
||||||
|
[`gcons*`](#gcons)
|
||||||
|
[`gappend`](#gappend)
|
||||||
|
[`gcombine`](#gcombine)
|
||||||
|
[`gfilter`](#gfilter)
|
||||||
|
[`gremove`](#gremove)
|
||||||
|
[`gtake`](#gtake)
|
||||||
|
[`gdrop`](#gdrop)
|
||||||
|
[`gtake-while`](#gtake-while)
|
||||||
|
[`gdrop-while`](#gdrop-while)
|
||||||
|
[`gdelete`](#gdelete)
|
||||||
|
[`gdelete-neighbor-dups`](#gdelete-neighbor-dups)
|
||||||
|
[`gindex`](#gindex)
|
||||||
|
[`gselect`](#gselect)
|
||||||
|
|
||||||
|
## Consuming generated values
|
||||||
|
[`generator->list`](#generator-list)
|
||||||
|
[`generator->reverse-list`](#generator-reverse-list)
|
||||||
|
[`generator->vector`](#generator-vector)
|
||||||
|
[`generator->vector!`](#generator-vector!)
|
||||||
|
[`generator->string`](#generator-string)
|
||||||
|
[`generator-fold`](#generator-fold)
|
||||||
|
[`generator-for-each`](#generator-for-each)
|
||||||
|
[`generator-find`](#generator-find)
|
||||||
|
[`generator-count`](#generator-count)
|
||||||
|
[`generator-any`](#generator-any)
|
||||||
|
[`generator-every`](#generator-every)
|
||||||
|
[`generator-unfold`](#generator-unfold)
|
||||||
|
|
||||||
|
# generator
|
||||||
|
|
||||||
|
(generator arg ...)
|
||||||
|
|
||||||
|
Returns a generator which produces each of this function's arguments in turn.
|
||||||
|
When given no arguments, returns an empty generator which provides no values.
|
||||||
|
|
||||||
|
# make-iota-generator
|
||||||
|
|
||||||
|
(make-iota-generator count)
|
||||||
|
(make-iota-generator count start)
|
||||||
|
(make-iota-generator count start step)
|
||||||
|
|
||||||
|
Returns a finite generator which produces a sequence of ``count`` numbers. The
|
||||||
|
sequence begins with ``start`` (default 0) and increases by ``step`` (default
|
||||||
|
1). If both ``start`` and ``step`` are exact, the generator produces exact
|
||||||
|
values; otherwise, it produces inexact ones. The exactness of ``count`` does not
|
||||||
|
affect the exactness of results.
|
||||||
|
|
||||||
|
Example: ``(generator->list (make-iota-generator 3 8))`` => (8 9 10)``
|
||||||
|
|
||||||
|
# make-range-generator
|
||||||
|
|
||||||
|
(make-range-generator start)
|
||||||
|
(make-range-generator start end)
|
||||||
|
(make-range-generator start end step)
|
||||||
|
|
||||||
|
Returns a generator which produces a sequence of numbers. The sequence begins
|
||||||
|
with ``start``, increases by ``step`` (default 1), and continues while the
|
||||||
|
number is less than ``end``, or forever if ``end`` is not provided. If both
|
||||||
|
``start`` and ``step`` are exact, the generator produces exact values;
|
||||||
|
otherwise, it produces inexact ones. The exactness of ``end`` does not affect
|
||||||
|
the exactness of the results.
|
||||||
|
|
||||||
|
Example: ``(generator->list (make-range-generator 3) 4) => (3 4 5 6)``
|
||||||
|
|
||||||
|
# make-coroutine-generator
|
||||||
|
|
||||||
|
(make-coroutine-generator proc)
|
||||||
|
|
||||||
|
Creates a generator from a coroutine. The ``proc`` argument should be a
|
||||||
|
procedure that takes a single argument ``yield``. When called,
|
||||||
|
``make-coroutine-generator`` immediately returns a generator ``g``. When ``g``
|
||||||
|
is called, ``proc`` runs until it calls ``yield``. Calling ``yield`` causes the
|
||||||
|
execution of ``proc`` to be suspended, and ``g`` returns the value passed to
|
||||||
|
``yield``.
|
||||||
|
|
||||||
|
Whether ``g`` is finite or infinite depends on the behaviour of ``proc``: if
|
||||||
|
``proc`` returns, it is the end of the sequence, and ``g`` will return an
|
||||||
|
end-of-file object from then on. The return value of ``proc`` is ignored.
|
||||||
|
|
||||||
|
# list->generator
|
||||||
|
|
||||||
|
(list->generator lis)
|
||||||
|
|
||||||
|
Returns a generator that produces each element of the list ``lis`` in turn.
|
||||||
|
Mutating ``lis`` will affect the results of the generator.
|
||||||
|
|
||||||
|
``list->generator`` and ``generator->list`` (when given no arguments) are
|
||||||
|
inverses up to ``equal?``; thus, for any list ``x``,
|
||||||
|
``(equal? x (generator->list (list->generator x))) => #t``.
|
||||||
|
|
||||||
|
# vector->generator
|
||||||
|
|
||||||
|
(vector->generator vec)
|
||||||
|
(vector->generator vec start)
|
||||||
|
(vector->generator vec start end)
|
||||||
|
|
||||||
|
Returns a generator that produces elements of ``vec``, in turn, from the index
|
||||||
|
``start`` (inclusive, default 0) to ``end`` (exclusive, default
|
||||||
|
``(vector-length vec)``). Mutating ``vec`` will affect the results of the
|
||||||
|
generator.
|
||||||
|
|
||||||
|
When given no arguments, ``vector->generator`` and ``generator->vector`` are
|
||||||
|
inverses up to ``equal?``; thus, for any vector ``x``, ``(equal? x
|
||||||
|
(generator->vector (vector->generator x))) => #t``.
|
||||||
|
|
||||||
|
# reverse-vector->generator
|
||||||
|
|
||||||
|
(reverse-vector->generator vec)
|
||||||
|
(reverse-vector->generator vec start)
|
||||||
|
(reverse-vector->generator vec start end)
|
||||||
|
|
||||||
|
Returns a generator that produces elements of ``vec``, in turn, from ``end``
|
||||||
|
(exclusive, default ``(vector-length vec)``) to ``start`` (inclusive, default
|
||||||
|
0), in reverse order of indices. Mutating ``vec`` will affect the results of the
|
||||||
|
generator.
|
||||||
|
|
||||||
|
# string->generator
|
||||||
|
|
||||||
|
(string->generator str)
|
||||||
|
(string->generator str start)
|
||||||
|
(string->generator str start end)
|
||||||
|
|
||||||
|
Returns a generator that produces characters of ``str``, in turn, from ``start``
|
||||||
|
(inclusive, default 0) to ``end`` (exclusive, default ``(string-length str)``).
|
||||||
|
Mutating ``str`` will affect the results of the generator.
|
||||||
|
|
||||||
|
When given no arguments, ``string->generator`` and ``generator->string`` are
|
||||||
|
inverses up to ``string=?``; thus, for any string ``s``, ``(string=? s
|
||||||
|
(generator->string (string->generator s))) => #t``.
|
||||||
|
|
||||||
|
# bytevector->generator
|
||||||
|
|
||||||
|
(bytevector->generator bv)
|
||||||
|
(bytevector->generator bv start)
|
||||||
|
(bytevector->generator bv start end)
|
||||||
|
|
||||||
|
Returns a generator that produces bytes of ``bv``, in turn, from ``start``
|
||||||
|
(inclusive, default 0) to ``end`` (exclusive, default ``(bytevector-length
|
||||||
|
bv)``). Mutating ``bv`` will affect the results of the generator.
|
||||||
|
|
||||||
|
# make-for-each-generator
|
||||||
|
|
||||||
|
(make-for-each-generator for-each obj)
|
||||||
|
|
||||||
|
Constructs a generator over any collection ``obj``, using a ``for-each``
|
||||||
|
procedure appropriate to ``obj``. This must be a procedure that, when called as
|
||||||
|
``(for-each proc obj)`` calls ``proc`` on each element of ``obj``. Examples of
|
||||||
|
such procedures are ``for-each``, ``string-for-each`` and ``vector-for-each``.
|
||||||
|
The value returned by ``for-each`` is ignored. The generator is finite if the
|
||||||
|
collection is finite.
|
||||||
|
|
||||||
|
``obj`` need not be a conventional one (such as a string, list, etc), as long as
|
||||||
|
``for-each`` can invoke a procedure on everything that counts as a member.
|
||||||
|
|
||||||
|
# make-unfold-generator
|
||||||
|
|
||||||
|
(make-unfold-generator stop? mapper successor seed)
|
||||||
|
|
||||||
|
A generator similar to [SRFI 1][2]'s ``unfold``.
|
||||||
|
|
||||||
|
The ``stop?`` predicate takes a seed value and determines whether to stop. The
|
||||||
|
``mapper`` procedure calculates a value to be returned by the generator from a
|
||||||
|
seed value. The ``successor`` procedure calculates the next seed value from
|
||||||
|
the current seed value.
|
||||||
|
|
||||||
|
For each call of the resulting generator, ``stop?`` is called with the current
|
||||||
|
seed value. If it returns true, then the generator returns an end-of-file
|
||||||
|
object. Otherwise, it applies ``mapper`` to the current seed value to get the
|
||||||
|
value to return, and uses ``successor`` to update the seed value.
|
||||||
|
|
||||||
|
The generator is finite unless ``stop?`` is a constant function returning
|
||||||
|
``#f``.
|
||||||
|
|
||||||
|
# gcons\*
|
||||||
|
|
||||||
|
(gcons\* item ... gen)
|
||||||
|
|
||||||
|
Returns a generator that adds ``item ...`` in front of ``gen``. Once each of
|
||||||
|
``item ...`` has been produced, the generator is guaranteed to tail-call
|
||||||
|
``gen``.
|
||||||
|
|
||||||
|
# gappend
|
||||||
|
|
||||||
|
(gappend gen ...)
|
||||||
|
|
||||||
|
Returns a generator that yields the items from the first argument generator, and
|
||||||
|
once it is exhausted, the second generator, and so forth.
|
||||||
|
|
||||||
|
If any of the argument generators are infinite, subsequent argument generators
|
||||||
|
will never be asked to produce any values.
|
||||||
|
|
||||||
|
# gcombine
|
||||||
|
|
||||||
|
(gcombine proc seed gen gen2 ...)
|
||||||
|
|
||||||
|
Returns a generator for mapping with state. It produces a sequence of sub-folds
|
||||||
|
over ``proc``.
|
||||||
|
|
||||||
|
The ``proc`` argument is a procedure that takes as many arguments as there are
|
||||||
|
argument generators, plus one. It is called as ``(proc v1 v2 ... seed)``, where
|
||||||
|
``v1 v2 ...`` are the values produced by the argument generators, and ``seed``
|
||||||
|
is the current seed value. It must return two values: the produced value and the
|
||||||
|
next seed. The generator is exhausted when any of its argument generators are
|
||||||
|
exhausted, at which time, the remaining argument generators are in an undefined
|
||||||
|
state.
|
||||||
|
|
||||||
|
# gfilter
|
||||||
|
|
||||||
|
(gfilter pred gen)
|
||||||
|
|
||||||
|
Returns a generator that produces items from ``gen``, except those for which
|
||||||
|
``pred`` would return ``#f``.
|
||||||
|
|
||||||
|
# gremove
|
||||||
|
|
||||||
|
(gremove pred gen)
|
||||||
|
|
||||||
|
Equivalent to ``(gfilter (lambda (x) (not (pred x))) gen)``.
|
||||||
|
|
||||||
|
# gtake
|
||||||
|
|
||||||
|
(gtake gen k)
|
||||||
|
(gtake gen k padding)
|
||||||
|
|
||||||
|
A generator analogue to [SRFI 1][2]'s ``take``. Returns a generator that
|
||||||
|
produces (at most) the first ``k`` items of ``gen``. If ``gen`` is exhausted
|
||||||
|
before it can produce ``k`` items, the rest will be made up by producing the
|
||||||
|
``padding`` value.
|
||||||
|
|
||||||
|
# gdrop
|
||||||
|
|
||||||
|
(gdrop gen k)
|
||||||
|
|
||||||
|
A generator analogue to [SRFI 1][2]'s ``drop``. Returns a generator that
|
||||||
|
skips the first (at most) ``k`` items of ``gen``, then produces the rest. If
|
||||||
|
``k`` is greater than, or equal to, the total number of items ``gen`` could
|
||||||
|
produce, an empty generator is produced instead.
|
||||||
|
|
||||||
|
# gtake-while
|
||||||
|
|
||||||
|
(gtake-while pred gen)
|
||||||
|
|
||||||
|
A generator analogue to [SRFI 1][2]'s ``take-while``. Returns a generator that
|
||||||
|
produces values from ``gen`` until ``pred`` returns ``#f`` on a value.
|
||||||
|
|
||||||
|
# gdrop-while
|
||||||
|
|
||||||
|
(gdrop-while pred gen)
|
||||||
|
|
||||||
|
A generator analogue to [SRFI 1][2]'s ``drop-while``. Returns a generator that
|
||||||
|
discards values from ``gen`` until ``pred`` returns ``#t`` for a value, and then
|
||||||
|
produces values from ``gen``.
|
||||||
|
|
||||||
|
# gdelete
|
||||||
|
|
||||||
|
(gdelete item gen)
|
||||||
|
(gdelete item gen =)
|
||||||
|
|
||||||
|
Returns a generator which produces the same items as ``gen``, except any items
|
||||||
|
that are the same as ``item`` up to ``=``, which defaults to ``equal?``. ``=``
|
||||||
|
is passed exactly two arguments, one of which is the value produced by ``gen``.
|
||||||
|
|
||||||
|
# gdelete-neighbor-dups
|
||||||
|
|
||||||
|
(gdelete-neighbor-dups gen)
|
||||||
|
(gdelete-neighbor-dups gen =)
|
||||||
|
|
||||||
|
Returns a generator which produces the same items as ``gen``, except any items
|
||||||
|
that are the same as the preceding items up to ``=``, which defaults to
|
||||||
|
``equal?``. ``=`` is passed exactly two arguments; the first of which is
|
||||||
|
produced by ``gen`` before the second.
|
||||||
|
|
||||||
|
# gindex
|
||||||
|
|
||||||
|
(gindex value-gen index-gen)
|
||||||
|
|
||||||
|
Returns a generator that produces elements of ``value-gen`` specified by the
|
||||||
|
indices (non-negative exact integers) produced by ``index-gen``. It is an error
|
||||||
|
if the indices are not strictly increasing, or if any index exceeds the number
|
||||||
|
of elements produced by ``value-gen``. The generator is exhausted when either of
|
||||||
|
``value-gen`` or ``index-gen`` is exhausted, at which time the other is in an
|
||||||
|
undefined state.
|
||||||
|
|
||||||
|
# gselect
|
||||||
|
|
||||||
|
(gselect value-gen truth-gen)
|
||||||
|
|
||||||
|
Returns a generator that produces elements of ``value-gen`` that correspond to
|
||||||
|
the values produced by ``truth-gen``. If the current value of ``truth-gen`` is
|
||||||
|
true, the current value of ``value-gen`` is produced; otherwise, the value is
|
||||||
|
skipped. The generator is exhausted when either of ``value-gen`` or
|
||||||
|
``truth-gen`` is exhausted, at which time the other is in an undefined state.
|
||||||
|
|
||||||
|
# generator->list
|
||||||
|
|
||||||
|
(generator->list gen)
|
||||||
|
(generator->list gen k)
|
||||||
|
|
||||||
|
Calls ``gen`` repeatedly to produce its values, then collects them into a list
|
||||||
|
and returns them. If ``k`` is omitted, ``gen`` will be asked to produce values
|
||||||
|
until it is exhausted; otherwise, only at most ``k``-many values will be
|
||||||
|
requested. It is an error for ``k`` to be anything other than a non-negative
|
||||||
|
integer.
|
||||||
|
|
||||||
|
# generator->reverse-list
|
||||||
|
|
||||||
|
(generator->reverse-list gen)
|
||||||
|
(generator->reverse-list gen k)
|
||||||
|
|
||||||
|
As ``generator->list``, but the returned list is in reverse order.
|
||||||
|
|
||||||
|
# generator->vector
|
||||||
|
|
||||||
|
(generator->vector gen)
|
||||||
|
(generator->vector gen k)
|
||||||
|
|
||||||
|
As ``generator->list``, but the returned result is a vector.
|
||||||
|
|
||||||
|
# generator->vector!
|
||||||
|
|
||||||
|
(generator->vector! vec at gen)
|
||||||
|
|
||||||
|
Calls ``gen`` repeatedly to produce its values, and puts them into ``vec``,
|
||||||
|
starting at index ``at``, until ``vec`` is full or ``gen`` is exhausted. Returns
|
||||||
|
the number of elements produced from ``gen``.
|
||||||
|
|
||||||
|
# generator->string
|
||||||
|
|
||||||
|
(generator->string gen)
|
||||||
|
(generator->string gen k)
|
||||||
|
|
||||||
|
Calls ``gen`` repeatedly to produce characters, and returns a newly-allocated
|
||||||
|
string of them. It is an error if ``gen`` does not produce only characters. If
|
||||||
|
``k`` is omitted, the generator will be asked to produce characters until it is
|
||||||
|
exhausted; otherwise, at most ``k`` characters will be requested. It is an error
|
||||||
|
for ``k`` to be anything other than a non-negative integer.
|
||||||
|
|
||||||
|
# generator-fold
|
||||||
|
|
||||||
|
(generator-fold proc seed gen1 gen2 ...)
|
||||||
|
|
||||||
|
An analogue of [SRFI 1][2]'s ``fold`` on values produced by the generator
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
When one generator argument ``gen`` is given, for each value ``v`` produced by
|
||||||
|
``gen``, ``proc`` is called as ``(proc v r)``, where ``r`` is the current
|
||||||
|
accumulated result; the initial value of ``r`` is ``seed``, and the return value
|
||||||
|
from ``proc`` becomes the new accumulated result. When ``gen`` is exhausted, the
|
||||||
|
accumulated result at the time is returned.
|
||||||
|
|
||||||
|
When more than one generator argument is given, ``proc`` is called on all the
|
||||||
|
values produced by all the generator arguments, followed by the current
|
||||||
|
accumulated result. The procedure returns when any of the generator arguments is
|
||||||
|
exhausted, at which time the others are in an undefined state.
|
||||||
|
|
||||||
|
# generator-for-each
|
||||||
|
|
||||||
|
(generator-for-each proc gen1 gen2 ...)
|
||||||
|
|
||||||
|
A generator analogue of ``for-each`` that consumes produced values with side
|
||||||
|
effects. ``proc`` is repeatedly applied to values produced by all the generator
|
||||||
|
arguments, until any of them is exhausted. The values returned by ``proc`` are
|
||||||
|
discarded. The procedure terminates when any of the argument generators is
|
||||||
|
exhausted, at which time the others are in an undefined state.
|
||||||
|
|
||||||
|
# generator-find
|
||||||
|
|
||||||
|
(generator-find pred gen)
|
||||||
|
|
||||||
|
Returns the first value produced by ``gen`` that satisfies the predicate
|
||||||
|
``pred``, or ``#f`` if no such value exists. If ``gen`` is infinite, this
|
||||||
|
procedure will not return if it cannot find an appropriate item.
|
||||||
|
|
||||||
|
# generator-count
|
||||||
|
|
||||||
|
(generator-count pred gen)
|
||||||
|
|
||||||
|
Returns the number of values that gen can produce which satisfy the predicate
|
||||||
|
``pred``. This procedure will not return if ``gen`` is infinite.
|
||||||
|
|
||||||
|
# generator-any
|
||||||
|
|
||||||
|
(generator-any pred gen)
|
||||||
|
|
||||||
|
Applies ``pred`` to each item produced by ``gen``. As soon as ``pred`` returns a
|
||||||
|
true value, the value is returned without consuming the rest of ``gen``. If
|
||||||
|
``gen`` is exhausted, returns ``#f``.
|
||||||
|
|
||||||
|
# generator-every
|
||||||
|
|
||||||
|
(generator-every pred gen)
|
||||||
|
|
||||||
|
Equivalent to ``(not (generator-any (lambda (x) (not (pred x))) gen))``.
|
||||||
|
|
||||||
|
# generator-unfold
|
||||||
|
|
||||||
|
(generator-unfold gen unfold arg ...)
|
||||||
|
|
||||||
|
Equivalent to ``(unfold eof-object? (lambda (x) x) (lambda (x) (gen)) arg
|
||||||
|
...)``, where ``unfold`` is the [SRFI 1][2] procedure of the same name.
|
||||||
|
|
||||||
|
[1]: http://srfi.schemers.org/srfi-121/srfi-121.html
|
||||||
|
[2]: http://srfi.schemers.org/srfi-1/srfi-1.html
|
|
@ -4,6 +4,12 @@ The `(srfi 18)` library provides multithreading support.
|
||||||
|
|
||||||
See the [Multithreading support SRFI documentation](http://srfi.schemers.org/srfi-18/srfi-18.html) for more information.
|
See the [Multithreading support SRFI documentation](http://srfi.schemers.org/srfi-18/srfi-18.html) for more information.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
Currently, ``thread-join!`` is not provided. While this is not an essential
|
||||||
|
primitive and can be worked around, code that relies on ``thread-join!`` being
|
||||||
|
present in this implementation will fail to compile.
|
||||||
|
|
||||||
- [`thread?`](#thread)
|
- [`thread?`](#thread)
|
||||||
- [`make-thread`](#make-thread)
|
- [`make-thread`](#make-thread)
|
||||||
- [`thread-name`](#thread-name)
|
- [`thread-name`](#thread-name)
|
||||||
|
|
47
docs/api/srfi/28.md
Normal file
47
docs/api/srfi/28.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# SRFI 28 - Basic format strings
|
||||||
|
|
||||||
|
Specifies a method of interpreting a Scheme string which contains a number of
|
||||||
|
escape sequences, into which other data is interpolated according to the
|
||||||
|
semantics of each sequence.
|
||||||
|
|
||||||
|
See the [SRFI document][1] for more information.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
Currently, this translates newline escape sequences into LF. This may cause
|
||||||
|
issues if this is ever used on Windows (which expects CRLF instead). Given that
|
||||||
|
Cyclone does not currently support Windows, this issue should not arise in
|
||||||
|
practice.
|
||||||
|
|
||||||
|
## Interface
|
||||||
|
|
||||||
|
# format
|
||||||
|
|
||||||
|
(format format-string [obj ...])
|
||||||
|
|
||||||
|
Processes ``format-string``, replacing any escape sequences in order with one or
|
||||||
|
more characters. These characters depend on the semantics of the escape
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
An 'escape sequence' is a two-character sequence in ``format-string``, where the
|
||||||
|
first character is a tilde ('~'). The following are all of the valid escape
|
||||||
|
codes, as well as their semantics:
|
||||||
|
|
||||||
|
- ``~a``: The corresponding value is inserted into the string as if printed by
|
||||||
|
``display``.
|
||||||
|
- ``~s``: The corresponding value is inserted into the string as if printed by
|
||||||
|
``write``.
|
||||||
|
- ``~%``: A newline is inserted.
|
||||||
|
- ``~~``: A literal tilde is inserted.
|
||||||
|
|
||||||
|
``~a`` and ``~s``, when encountered, require a corresponding Scheme value to be
|
||||||
|
present as an argument to ``format``. The values provided in ``obj ...`` are
|
||||||
|
used by the escape sequences in order. It is an error if fewer values are
|
||||||
|
provided than escape sequences which require them. ``~%`` and ``~~`` do not need
|
||||||
|
a corresponding value.
|
||||||
|
|
||||||
|
Example: The call ``(format "This is the ~ast example: ~s~%" 1 '(foo bar 17))``
|
||||||
|
would produce the string ``"This is the 1st example: (foo bar 17)
|
||||||
|
"`` (note the newline).
|
||||||
|
|
||||||
|
[1]: http://srfi.schemers.org/srfi-28/srfi-28.html
|
247
docs/api/srfi/60.md
Normal file
247
docs/api/srfi/60.md
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
# SRFI 60 - Integers as bits
|
||||||
|
|
||||||
|
Various operations designed to work on integers as strings of bits efficiently.
|
||||||
|
|
||||||
|
See the [SRFI document][1] for more information.
|
||||||
|
|
||||||
|
## Bitwise operations
|
||||||
|
[`logand`](#logand)
|
||||||
|
[`logior`](#logior)
|
||||||
|
[`logxor`](#logxor)
|
||||||
|
[`lognot`](#lognot)
|
||||||
|
[`logtest`](#logtest)
|
||||||
|
[`bitwise-and`](#bitwise-and)
|
||||||
|
[`bitwise-ior`](#bitwise-ior)
|
||||||
|
[`bitwise-xor`](#bitwise-xor)
|
||||||
|
[`bitwise-not`](#bitwise-not)
|
||||||
|
[`bitwise-if`](#bitwise-if)
|
||||||
|
[`bitwise-merge`](#bitwise-merge)
|
||||||
|
[`any-bits-set?`](#any-bits-set)
|
||||||
|
|
||||||
|
## Integer properties
|
||||||
|
[`logcount`](#logcount)
|
||||||
|
[`log2-binary-factors`](#log2-binary-factors)
|
||||||
|
[`bit-count`](#bit-count)
|
||||||
|
[`integer-length`](#integer-length)
|
||||||
|
[`first-set-bit`](#first-set-bit)
|
||||||
|
|
||||||
|
## Bit within word
|
||||||
|
[`logbit?`](#logbit)
|
||||||
|
[`bit-set?`](#bit-set)
|
||||||
|
[`copy-bit`](#copy-bit)
|
||||||
|
|
||||||
|
## Field of bits
|
||||||
|
[`bit-field`](#bit-field)
|
||||||
|
[`copy-bit-field`](#copy-bit-field)
|
||||||
|
[`ash`](#ash)
|
||||||
|
[`arithmetic-shift`](#ash)
|
||||||
|
[`rotate-bit-field`](#rotate-bit-field)
|
||||||
|
|
||||||
|
## Bits as booleans
|
||||||
|
[`integer->list`](#integer-list)
|
||||||
|
[`list->integer`](#list-integer)
|
||||||
|
[`booleans->integer`](#booleans-integer)
|
||||||
|
|
||||||
|
# logand
|
||||||
|
|
||||||
|
(logand n1 ...)
|
||||||
|
|
||||||
|
Returns the integer which is the bitwise-AND of the arguments.
|
||||||
|
|
||||||
|
Example: ``(number->string (logand #b1100 #b1010) 2) => "1000"``
|
||||||
|
|
||||||
|
# bitwise-and
|
||||||
|
|
||||||
|
Synonym for ``logand``.
|
||||||
|
|
||||||
|
# logior
|
||||||
|
|
||||||
|
(logior n1 ...)
|
||||||
|
|
||||||
|
Returns the integer which is the bitwise-OR of the arguments.
|
||||||
|
|
||||||
|
Example: ``(number->string (logior #b1100 #b1010) 2) => "1110"``
|
||||||
|
|
||||||
|
# bitwise-ior
|
||||||
|
|
||||||
|
Synonym for ``logior``.
|
||||||
|
|
||||||
|
# logxor
|
||||||
|
|
||||||
|
(logxor n1 ...)
|
||||||
|
|
||||||
|
Returns the integer which is the bitwise-XOR of the arguments.
|
||||||
|
|
||||||
|
Example: ``(number->string (logxor #b1100 #b1010) 2) => "110"``
|
||||||
|
|
||||||
|
# bitwise-xor
|
||||||
|
|
||||||
|
Synonym for ``logxor``.
|
||||||
|
|
||||||
|
# lognot
|
||||||
|
|
||||||
|
(lognot n)
|
||||||
|
|
||||||
|
Returns the integer which is the one's-complement of the argument.
|
||||||
|
|
||||||
|
# bitwise-not
|
||||||
|
|
||||||
|
Synonym for ``lognot``.
|
||||||
|
|
||||||
|
# bitwise-if
|
||||||
|
|
||||||
|
(bitwise-if mask n0 n1)
|
||||||
|
|
||||||
|
Returns an integer composed of some bits from ``n0`` and some bits from ``n1``.
|
||||||
|
A bit of the result is taken from ``n0`` if the corresponding bit of ``mask`` is
|
||||||
|
1, and from ``n1`` otherwise.
|
||||||
|
|
||||||
|
# bitwise-merge
|
||||||
|
|
||||||
|
Synonym for ``bitwise-if``.
|
||||||
|
|
||||||
|
# logtest
|
||||||
|
|
||||||
|
(logtest j k)
|
||||||
|
|
||||||
|
Equivalent to ``(not (zero? (logand j k)))``.
|
||||||
|
|
||||||
|
Example: ``(logtest #b0100 #b1011) => #f``
|
||||||
|
|
||||||
|
# any-bits-set?
|
||||||
|
|
||||||
|
Synonym for ``logtest``.
|
||||||
|
|
||||||
|
# logcount
|
||||||
|
|
||||||
|
(logcount n)
|
||||||
|
|
||||||
|
Returns the number of bits in ``n``. If ``n`` is positive, the 1-bits in its
|
||||||
|
binary representation are counted. If negative, the 0-bits in its
|
||||||
|
two's-complement binary representation are counted. If 0, then 0 is returned.
|
||||||
|
|
||||||
|
Example: ``(logcount #b10101010) => 4``
|
||||||
|
|
||||||
|
# bit-count
|
||||||
|
|
||||||
|
Synonym for ``logcount``.
|
||||||
|
|
||||||
|
# integer-length
|
||||||
|
|
||||||
|
(integer-length n)
|
||||||
|
|
||||||
|
Returns the number of bits necessary to represent ``n``.
|
||||||
|
|
||||||
|
Example: ``(integer-length #b1011) => 4``
|
||||||
|
|
||||||
|
# log2-binary-factors
|
||||||
|
|
||||||
|
(log2-binary-factors n)
|
||||||
|
|
||||||
|
Returns the bit-index of the least-significant 1-bit in ``n``. If ``n`` contains
|
||||||
|
no 1-bits, -1 is returned.
|
||||||
|
|
||||||
|
Example: ``(log2-binary-factors 4) => 2``
|
||||||
|
|
||||||
|
# first-set-bit
|
||||||
|
|
||||||
|
Synonym for ``log2-binary-factors``
|
||||||
|
|
||||||
|
# logbit?
|
||||||
|
|
||||||
|
(logbit? index n)
|
||||||
|
|
||||||
|
Equivalent to ``(logtest (exact (expt 2 index)) n)``.
|
||||||
|
|
||||||
|
Example: ``(logbit? 1 #b1101) => #f``
|
||||||
|
|
||||||
|
# bit-set?
|
||||||
|
|
||||||
|
Synonym for ``logbit?``.
|
||||||
|
|
||||||
|
# copy-bit
|
||||||
|
|
||||||
|
(copy-bit index from bit)
|
||||||
|
|
||||||
|
Returns ``from``, except in the ``index``th bit, which is 1 if ``bit`` is #t,
|
||||||
|
and 0 if ``bit`` is #f.
|
||||||
|
|
||||||
|
Example: ``(number->string (copy-bit 2 #b1111 #f) 2) => "1011"``
|
||||||
|
|
||||||
|
# bit-field
|
||||||
|
|
||||||
|
(bit-field n start end)
|
||||||
|
|
||||||
|
Returns the integer composed of the ``start`` (inclusive) through ``end``
|
||||||
|
(exclusive) bits of ``n``. The ``start``th bit becomes the 0th bit in the
|
||||||
|
result.
|
||||||
|
|
||||||
|
Example: ``(number->string (bit-field #b1101101010 0 4) 2) => "1010"``
|
||||||
|
|
||||||
|
# copy-bit-field
|
||||||
|
|
||||||
|
(copy-bit-field to from start end)
|
||||||
|
|
||||||
|
Returns ``to``, except possibly in the ``start`` (inclusive) through ``end``
|
||||||
|
(exclusive) bits, which are the same as those of ``from``. The 0th bit of
|
||||||
|
``from`` becomes the ``start``th bit of the result.
|
||||||
|
|
||||||
|
Example: ``(number->string (copy-bit-field #b1101101010 0 0 4) 2) =>
|
||||||
|
"1101100000"``
|
||||||
|
|
||||||
|
# ash
|
||||||
|
|
||||||
|
(ash n count)
|
||||||
|
|
||||||
|
Equivalent to ``(exact (floor (* n (expt 2 count))))``.
|
||||||
|
|
||||||
|
Example: ``(number->string (ash #b1010 -1) 2) => "101"``
|
||||||
|
|
||||||
|
# arithmetic-shift
|
||||||
|
|
||||||
|
Synonym for ``ash``.
|
||||||
|
|
||||||
|
# rotate-bit-field
|
||||||
|
|
||||||
|
(rotate-bit-field n count start end)
|
||||||
|
|
||||||
|
Returns ``n`` with the bit-field from ``start`` to ``end`` cyclically permuted
|
||||||
|
by ``count`` bits towards high-order.
|
||||||
|
|
||||||
|
Example: ``(number->string (rotate-bit-field #b0100 3 0 4) 2) => "10"``
|
||||||
|
|
||||||
|
# reverse-bit-field
|
||||||
|
|
||||||
|
(reverse-bit-field n start end)
|
||||||
|
|
||||||
|
Returns ``n`` with the order of bits ``start`` to ``end`` reversed.
|
||||||
|
|
||||||
|
Example: ``(number->string (reverse-bit-field #b10100111 0 8) 2) =>
|
||||||
|
"11100101")``
|
||||||
|
|
||||||
|
# integer->list
|
||||||
|
|
||||||
|
(integer->list k)
|
||||||
|
|
||||||
|
(integer->list k len)
|
||||||
|
|
||||||
|
Returns a list of ``len`` booleans corresponding to each bit of the non-negative
|
||||||
|
integer ``k``. ``#t`` is coded for each 1; ``#f`` for each 0. ``len`` defaults
|
||||||
|
to ``(integer-length k)``.
|
||||||
|
|
||||||
|
# list->integer
|
||||||
|
|
||||||
|
(list->integer list)
|
||||||
|
|
||||||
|
Returns an integer formed from the booleans in ``list``, which must consist only
|
||||||
|
of booleans. A 1 bit is coded for each ``#t``; a 0 bit for each ``#f``.
|
||||||
|
``integer->list`` and ``list->integer`` are inverses up to ``equal?``: thus, for
|
||||||
|
any ``x``, ``(equal x (integer->list (list->integer x))) => #t``.
|
||||||
|
|
||||||
|
# booleans->integer
|
||||||
|
|
||||||
|
(booleans->integer b1 ...)
|
||||||
|
|
||||||
|
Equivalent to ``(list->integer (list b1 ...))``.
|
||||||
|
|
||||||
|
[1]: http://srfi.schemers.org/srfi-60/srfi-60.html
|
|
@ -11,6 +11,18 @@ Hash tables are widely recognised as a fundamental data structure for a wide var
|
||||||
|
|
||||||
See the [SRFI document](http://srfi.schemers.org/srfi-69/srfi-69.html) for more information.
|
See the [SRFI document](http://srfi.schemers.org/srfi-69/srfi-69.html) for more information.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
Hash table size must be strictly less than 536,870,909.
|
||||||
|
|
||||||
|
The default implementation of record hashing is severely suboptimal - if you
|
||||||
|
want to store records in a hash table, use a custom hashing function.
|
||||||
|
|
||||||
|
This implementation does not distinguish ``hash`` and ``hash-by-identity``.
|
||||||
|
Additionally, symbol hashing is done by string-hashing the result of
|
||||||
|
``symbol->string`` on the symbol, making symbols identical to strings for the
|
||||||
|
purpose of hash table key performance.
|
||||||
|
|
||||||
## Type constructors and predicate
|
## Type constructors and predicate
|
||||||
[`make-hash-table`](#make-hash-table)
|
[`make-hash-table`](#make-hash-table)
|
||||||
[`hash-table?`](#hash-table)
|
[`hash-table?`](#hash-table)
|
||||||
|
|
83
srfi/60.scm
83
srfi/60.scm
|
@ -1,23 +1,32 @@
|
||||||
;;; "60.scm", bit access and operations for integers for Scheme
|
#|
|
||||||
;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
|
| Copyright (c) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
|
||||||
;;; Copyright (C) 2017 Koz Ross
|
| Copyright (c) 2017, Koz Ross
|
||||||
;
|
|
|
||||||
;Permission to copy this software, to modify it, to redistribute it,
|
| All rights reserved.
|
||||||
;to distribute modified versions, and to use it for any purpose is
|
|
|
||||||
;granted, subject to the following restrictions and understandings.
|
| Redistribution and use in source and binary forms, with or without
|
||||||
;
|
| modification, are permitted provided that the following conditions are met:
|
||||||
;1. Any copy made of this software must include this copyright notice
|
| * Redistributions of source code must retain the above copyright
|
||||||
;in full.
|
| notice, this list of conditions and the following disclaimer.
|
||||||
;
|
| * Redistributions in binary form must reproduce the above copyright
|
||||||
;2. I have made no warranty or representation that the operation of
|
| notice, this list of conditions and the following disclaimer in the
|
||||||
;this software will be error-free, and I am under no obligation to
|
| documentation and/or other materials provided with the distribution.
|
||||||
;provide any services, by way of maintenance, update, or otherwise.
|
| * Neither the name of Cyclone nor the
|
||||||
;
|
| names of its contributors may be used to endorse or promote products
|
||||||
;3. In conjunction with products arising from the use of this
|
| derived from this software without specific prior written permission.
|
||||||
;material, there shall be no use of my name in any advertising,
|
|
|
||||||
;promotional, or sales literature without prior written consent in
|
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
;each case.
|
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
| DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|#
|
||||||
|
|
||||||
(define-c raw-logand
|
(define-c raw-logand
|
||||||
"(void* data, int argc, closure _, object k, object x, object y)"
|
"(void* data, int argc, closure _, object k, object x, object y)"
|
||||||
"Cyc_check_int(data, x);
|
"Cyc_check_int(data, x);
|
||||||
|
@ -99,16 +108,24 @@
|
||||||
|
|
||||||
(define bit-count logcount)
|
(define bit-count logcount)
|
||||||
|
|
||||||
(define (integer-length x)
|
(define-c integer-length
|
||||||
(exact (ceiling (log (+ x 1) 2))))
|
"(void* data, int argc, closure _, object k, object x)"
|
||||||
|
"Cyc_check_int(data, x);
|
||||||
|
int input = (int)unbox_number(x);
|
||||||
|
int res = 0;
|
||||||
|
while (input) {
|
||||||
|
res++;
|
||||||
|
input >>= 1;
|
||||||
|
};
|
||||||
|
return_closcall1(data, k, obj_int2obj(res));")
|
||||||
|
|
||||||
(define (log2-binary-factors n)
|
(define (log2-binary-factors n)
|
||||||
(- (integer-length (logand n (- n))) 1))
|
(- (integer-length (raw-logand n (- n))) 1))
|
||||||
|
|
||||||
(define first-set-bit log2-binary-factors)
|
(define first-set-bit log2-binary-factors)
|
||||||
|
|
||||||
(define (logbit? index n)
|
(define (logbit? index n)
|
||||||
(logtest (exact (expt 2 index)) n))
|
(logtest (ash 1 index) n))
|
||||||
|
|
||||||
(define bit-set? logbit?)
|
(define bit-set? logbit?)
|
||||||
|
|
||||||
|
@ -126,8 +143,22 @@
|
||||||
(ash from start)
|
(ash from start)
|
||||||
to))
|
to))
|
||||||
|
|
||||||
(define (ash x y)
|
(define-c ash
|
||||||
(exact (floor (* x (expt 2 y)))))
|
"(void* data, int argc, closure _, object k, object x, object y)"
|
||||||
|
"Cyc_check_int(data, x);
|
||||||
|
Cyc_check_int(data,y);
|
||||||
|
int bf = (int)unbox_number(x);
|
||||||
|
int shift = (int)unbox_number(y);
|
||||||
|
if (shift > 0) {
|
||||||
|
for (int i = 0; i < shift; i++) {
|
||||||
|
bf *= 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < abs(shift); i++) {
|
||||||
|
bf /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_closcall1(data, k, obj_int2obj(bf))")
|
||||||
|
|
||||||
(define arithmetic-shift ash)
|
(define arithmetic-shift ash)
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
;;;; doesn't have them yet. This will need to be modified accordingly once
|
;;;; doesn't have them yet. This will need to be modified accordingly once
|
||||||
;;;; this support is provided.
|
;;;; this support is provided.
|
||||||
(define-library (srfi 60)
|
(define-library (srfi 60)
|
||||||
(import (scheme base)
|
(import
|
||||||
(scheme inexact))
|
(scheme base))
|
||||||
(export
|
(export
|
||||||
any-bits-set? arithmetic-shift ash
|
any-bits-set? arithmetic-shift ash
|
||||||
bit-count bit-field bit-set? bitwise-and bitwise-if bitwise-ior
|
bit-count bit-field bit-set? bitwise-and bitwise-if bitwise-ior
|
||||||
|
|
Loading…
Add table
Reference in a new issue