Next: , Previous: , Up: objects   [Index]


13.18 Cflonum objects

Cflonums are complex numbers having a flonum as real part and flonum as imaginary part. A cflonum is a fixed length memory block referenced by machine words tagged as vectors. The first machine word of a cflonum block is tagged has cflonum in its least significant bits and it has the most significant bits set to zero.

|------------------------|-------------| reference to cflonum
      heap pointer         vector tag

|------------------------|-------------| cflonum first word
   all set to zero         cflonum tag

A cflonum memory block is 4 words wide; a reference to the real part is stored in the second word and a reference to the imaginary part is stored in the third word

   1st word     2nd word     3rd word     4th word
|------------|------------|------------|------------|
 tagged word   real part    imag part     unused

Basic operations

Cflonums are allocated on the Scheme heap as follows:

ikpcb_t * pcb   = ik_the_pcb();
ikptr_t   s_cf;

s_cf = ik_safe_alloc(pcb, cflonum_size) | vector_tag;
IK_CFLONUM_TAG(s_cf) = cflonum_tag;

after allocation we must always initialise the real and imaginary parts 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_re = the_real;
ikptr_t   s_im = the_imag;
ikptr_t   s_cf;

pcb->root9 = &s_re;
pcb->root8 = &s_im;
{
  s_rn = ik_safe_alloc(pcb, cflonum_size) | vector_tag;
}
pcb->root8 = NULL;
pcb->root9 = NULL;

IK_CFLONUM_TAG(s_cf) = cflonum_tag;
IK_CFLONUM_REP(s_cf) = s_re;
IK_CFLONUM_IMP(s_cf) = s_im;

notice that, as in this example, when a new cflonum object is allocated after the allocation of the real and imaginary objects: we do not need to call ik_signal_dirt_in_page_of_pointer() for s_cf because the cflonum is on the Scheme heap’s nursery, so it will for sure be scanned at the next garbage collection.

If we allocate the cflonum object first, then the real and imaginary objects, we want to follow this pattern:

ikpcb_t *  pcb  = ik_the_pcb();
double     rep  = the_real_part;
double     imp  = the_imag_part;
ikptr_t    s_cf = ik_safe_alloc(pcb, cflonum_size) | vector_tag;
IK_CFLONUM_TAG(s_cf) = cflonum_tag;

pcb->root9 = &s_cf;
{
  IK_ASS(IK_CFLONUM_REAL(s_cf), \
     ika_flonum_from_double(pcb, rep));
  IK_SIGNAL_DIRT(pcb, IK_CFLONUM_REAL_PTR(s_cf));

  IK_ASS(IK_CFLONUM_IMAG(s_cf), \
     ika_flonum_from_double(pcb, imp));
  IK_SIGNAL_DIRT(pcb, IK_CFLONUM_IMAG_PTR(s_cf));
}
pcb->root9 = NULL;

or:

ikpcb_t *  pcb  = ik_the_pcb();
double     rep  = the_real_part;
double     imp  = the_imag_part;
ikptr_t    s_cf = ika_cflonum_from_doubles(pcb, rep, imp);

To set or retrieve the real and imaginary parts we do:

ikptr_t  s_cf = the_cflonum;
ikptr_t  s_re;
ikptr_t  s_im;

s_re = IK_CFLONUM_REAL(s_cf);
s_im = IK_CFLONUM_IMAG(s_cf);

IK_CFLONUM_REAL(s_cf) = s_re;
IK_SIGNAL_DIRT(pcb, IK_CFLONUM_REAL_PTR(s_cf));

IK_CFLONUM_IMAG(s_cf) = s_im;
IK_SIGNAL_DIRT(pcb, IK_CFLONUM_IMAG_PTR(s_cf));
Preprocessor Symbol: cflonum_size

The number of bytes to allocate to hold a cflonum memory block.

Preprocessor Symbol: cflonum_tag

The tag of ikptr_t values used as first words in cflonum memory blocks.

Preprocessor Symbol: disp_cflonum_tag

Displacement of secondary tag word. The number of bytes to add to an untagged pointer to cflonum to get the pointer to the first byte in the word holding the cflonum tag.

Preprocessor Symbol: disp_cflonum_real
Preprocessor Symbol: disp_cflonum_imag

Displacements of real and imaginary parts. The number of bytes to add to an untagged pointer to cflonum to get the pointer to the first byte of the reference to the real or imaginary part.

Preprocessor Symbol: off_cflonum_tag

An integer to add to add to a tagged ikptr_t pointer to cflonum to get the pointer to the first byte in the word holding the cflonum tag.

Preprocessor Symbol: off_cflonum_real
Preprocessor Symbol: off_cflonum_imag

An integer to add to a tagged ikptr_t pointer to cflonum to get the pointer to the first byte of the words referencing the real or imaginary part.

Convenience preprocessor macros

Preprocessor Macro: int IK_IS_CFLONUM (ikptr_t obj)

Return true if obj is a cflonum object; otherwise return false.

Preprocessor Macro: ikptr_t IK_CFLONUM_REAL (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_IMAG (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_REP (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_IMP (ikptr_t X)

Evaluate to the location of the real and imaginary parts in the cflonum memory block; X must be a tagged pointer to cflonum object. A use of these macros can appear both as operand and as left–side of an assignment:

ikptr_t  s_cf = the_cflonum;
ikptr_t  s_re;

s_re = IK_CFLONUM_REAL(s_cf);

IK_CFLONUM_REAL(s_cf) = s_re;
IK_SIGNAL_DIRT(pcb, s_cf);
Preprocessor Macro: ikptr_t IK_CFLONUM_REAL_PTR (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_IMAG_PTR (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_REP_PTR (ikptr_t X)
Preprocessor Macro: ikptr_t IK_CFLONUM_IMP_PTR (ikptr_t X)

Evaluate to a pointer to the real and imaginary parts in the cflonum memory block; X must be a tagged pointer to cflonum object. These macros are useful to build the second argument to calls to ik_signal_dirt_in_page_of_pointer().

Operations on cflonums

Function: int ik_is_cflonum (ikptr_t obj)

Return true if obj is a cflonum object.

Function: ikptr_t iku_cflonum_alloc_and_init (ikpcb_t * pcb, double re, double im)

Allocate a cflonum and its flonum components using ik_unsafe_alloc() and return a tagged reference to it. No garbage collection is run while this function is evaluating.

Function: ikptr_t ika_cflonum_from_doubles (ikpcb_t * pcb, double re, double im)

Allocate a cflonum and its flonum components using ik_safe_alloc() and return a tagged reference to it. This function makes use of pcb->root9.

This function takes care of calling ik_signal_dirt_in_page_of_pointer() when appropriate.


Next: , Previous: , Up: objects   [Index]