Next: objects flonums, Previous: objects integers, Up: objects [Index]
Ratnums are exact rational numbers, having a fixnum or bignum as numerator and a fixnum or bignum as denominator; the numerator is always non–zero; the denominator is always strictly positive, the sign of a ratnum is the sign of the numerator.
A ratnum is a fixed length memory block referenced by machine words tagged as vectors. The first machine word of a ratnum block is tagged has ratnum in its least significant bits and it has the most significant bits set to zero.
|------------------------|-------------| reference to ratnum heap pointer vector tag |------------------------|-------------| ratnum first word all set to zero ratnum tag
A ratnum memory block is 4 words wide; a reference to the numerator is stored in the second word and a reference to the denominator is stored in the third word:
1st word 2nd word 3rd word 4th word |------------|------------|------------|------------| tagged word numerator denominator unused
Ratnums are allocated on the Scheme heap as follows:
ikpcb_t * pcb = ik_the_pcb(); ikptr_t s_rn; s_rn = ik_safe_alloc(pcb, ratnum_size) | vector_tag; IK_RATNUM_TAG(s_rn) = ratnum_tag;
after allocation we must always initialise the numerator and denominator fields to some correct value before running the next garbage collection. A full allocation and initialisation is as follows:
ikpcb_t * pcb = ik_the_pcb(); ikptr_t s_num = the_numerator; ikptr_t s_den = the_denominator; ikptr_t s_rn; pcb->root9 = &s_num; pcb->root8 = &s_den; { s_rn = ik_safe_alloc(pcb, ratnum_size) | vector_tag; } pcb->root8 = NULL; pcb->root9 = NULL; IK_RATNUM_TAG(s_rn) = ratnum_tag; IK_RATNUM_NUM(s_rn) = s_num; IK_RATNUM_DEN(s_rn) = s_den;
notice that, as in this example, when a new ratnum object is allocated
after the allocation of the numerator and denominator objects: we do not
need to call ik_signal_dirt_in_page_of_pointer()
for s_rn
because the ratnum is on the Scheme heap’s nursery, so it will for sure
be scanned at the next garbage collection.
If we allocate the ratnum object first, then the numerator and denominator objects, we want to follow this pattern:
ikpcb_t * pcb = ik_the_pcb(); iksword_t num = the_numerator; iksword_t den = the_denominator; ikptr_t s_rn = ik_safe_alloc(pcb, ratnum_size) | vector_tag; IK_RATNUM_TAG(s_rn) = ratnum_tag; pcb->root9 = &s_rn; { IK_ASS(IK_RATNUM_NUM(s_rn), \ ika_integer_from_sword(pcb, num)); IK_SIGNAL_DIRT(pcb, IK_RATNUM_NUM_PTR(s_rn)); IK_ASS(IK_RATNUM_DEN(s_rn), \ ika_integer_from_sword(pcb, den)); IK_SIGNAL_DIRT(pcb, IK_RATNUM_DEN_PTR(s_rn)); } pcb->root9 = NULL;
To set or retrieve the numerator and denominator we do:
ikptr_t s_rn = the_ratnum; ikptr_t s_num; ikptr_t s_den; s_num = IK_RATNUM_NUM(s_rn); s_den = IK_RATNUM_DEN(s_rn); IK_RATNUM_NUM(s_rn) = s_num; IK_SIGNAL_DIRT(pcb, IK_RATNUM_NUM_PTR(s_rn)); IK_RATNUM_DEN(s_rn) = s_den; IK_SIGNAL_DIRT(pcb, IK_RATNUM_DEN_PTR(s_rn));
The number of bytes to allocate to hold a ratnum memory block.
The tag of ikptr_t
values used as first words in ratnum memory blocks.
Displacement of secondary tag word. The number of bytes to add to an untagged pointer to ratnum to get the pointer to the first byte in the word holding the ratnum tag.
Displacements of numerator and denominator. The number of bytes to add to an untagged pointer to ratnum to get the pointer to the first byte of the reference to the numerator or denominator.
An integer to add to add to a tagged ikptr_t
pointer to ratnum to get
the pointer to the first byte in the word holding the ratnum tag.
An integer to add to a tagged ikptr_t
pointer to ratnum to get the
pointer to the first byte of the words referencing the numerator or
denominator.
Evaluate to true if obj is a ratnum object; otherwise evaluate to false.
Evaluate to the location of the first word in the ratnum memory block; X must be a tagged pointer to a ratnum object. A use of this macro can appear both as operand and as left–side of an assignment.
Evaluate to the location of the numerator or denominator in the ratnum memory block; X must be a tagged pointer to a ratnum object. A use of these macros can appear both as operand and as left–side of an assignment:
ikptr_t s_rn = the_ratnum; ikptr_t s_num; ikptr_t s_den; s_num = IK_RATNUM_NUM(s_rn); s_den = IK_RATNUM_NUM(s_rn); IK_RATNUM_NUM(s_rn) = s_num; IK_SIGNAL_DIRT(pcb, IK_RATNUM_NUM_PTR(s_rn)); IK_RATNUM_DEN(s_rn) = s_den; IK_SIGNAL_DIRT(pcb, IK_RATNUM_DEN_PTR(s_rn));
Evaluate to a pointer to the location of the numerator and denominator
objects in X, which must be a tagged pointer to a ratnum object.
These macros are useful to build the second argument for calls to
ik_signal_dirt_in_page_of_pointer()
.
Return true if obj is a ratnum object.
Allocate a new ratnum object using ik_safe_alloc()
and return a
tagged reference to it. The fields are left uninitialised.
Allocate a new ratnum object using ik_safe_alloc()
and return a
tagged reference to it. Both the fields are set to the fixnum zero.
Next: objects flonums, Previous: objects integers, Up: objects [Index]