single-torrix.c

     
   1  //! @file single-torrix.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
   8  
   9  //! @section License
  10  //!
  11  //! This program is free software; you can redistribute it and/or modify it 
  12  //! under the terms of the GNU General Public License as published by the 
  13  //! Free Software Foundation; either version 3 of the License, or 
  14  //! (at your option) any later version.
  15  //!
  16  //! This program is distributed in the hope that it will be useful, but 
  17  //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  //! more details. You should have received a copy of the GNU General Public 
  20  //! License along with this program. If not, see [http://www.gnu.org/licenses/].
  21  
  22  //! @section Synopsis
  23  //!
  24  //! REAL vector and matrix support.
  25  
  26  #include "a68g.h"
  27  #include "a68g-torrix.h"
  28  
  29  //! @brief Push description for diagonal of square matrix.
  30  
  31  PROP_T genie_diagonal_function (NODE_T * p)
  32  {
  33    NODE_T *q = SUB (p);
  34    BOOL_T name = (BOOL_T) (IS_REF (MOID (p)));
  35    int k = 0;
  36    if (IS (q, TERTIARY)) {
  37      A68_INT x;
  38      GENIE_UNIT (q);
  39      POP_OBJECT (p, &x, A68_INT);
  40      k = VALUE (&x);
  41      FORWARD (q);
  42    }
  43    GENIE_UNIT (NEXT (q));
  44    MOID_T *m = (name ? SUB_MOID (NEXT (q)) : MOID (NEXT (q)));
  45    ADDR_T scope = PRIMAL_SCOPE;
  46    if (name) {
  47      A68_REF z;
  48      POP_REF (p, &z);
  49      CHECK_REF (p, z, MOID (SUB (p)));
  50      scope = REF_SCOPE (&z);
  51      PUSH_REF (p, *DEREF (A68_REF, &z));
  52    }
  53    A68_ROW row; A68_ARRAY *arr; A68_TUPLE *tup1, *tup2;
  54    POP_OBJECT (p, &row, A68_ROW);
  55    GET_DESCRIPTOR2 (arr, tup1, tup2, &row);
  56    if (ROW_SIZE (tup1) != ROW_SIZE (tup2)) {
  57      diagnostic (A68_RUNTIME_ERROR, p, ERROR_NO_SQUARE_MATRIX, m);
  58      exit_genie (p, A68_RUNTIME_ERROR);
  59    }
  60    if (ABS (k) >= ROW_SIZE (tup1)) {
  61      diagnostic (A68_RUNTIME_ERROR, p, ERROR_INDEX_OUT_OF_BOUNDS);
  62      exit_genie (p, A68_RUNTIME_ERROR);
  63    }
  64    m = (name ? SUB_MOID (p) : MOID (p));
  65    A68_ROW new_row = heap_generator (p, m, DESCRIPTOR_SIZE (1));
  66    A68_ARRAY new_arr;
  67    DIM (&new_arr) = 1;
  68    MOID (&new_arr) = m;
  69    ELEM_SIZE (&new_arr) = ELEM_SIZE (arr);
  70    SLICE_OFFSET (&new_arr) = SLICE_OFFSET (arr);
  71    FIELD_OFFSET (&new_arr) = FIELD_OFFSET (arr);
  72    ARRAY (&new_arr) = ARRAY (arr);
  73    A68_TUPLE new_tup;
  74    LWB (&new_tup) = 1;
  75    UPB (&new_tup) = ROW_SIZE (tup1) - ABS (k);
  76    SHIFT (&new_tup) = SHIFT (tup1) + SHIFT (tup2) - k * SPAN (tup2);
  77    if (k < 0) {
  78      SHIFT (&new_tup) -= (-k) * (SPAN (tup1) + SPAN (tup2));
  79    }
  80    SPAN (&new_tup) = SPAN (tup1) + SPAN (tup2);
  81    K (&new_tup) = 0;
  82    PUT_DESCRIPTOR (new_arr, new_tup, &new_row);
  83    if (name) {
  84      A68_REF ref_new = heap_generator (p, MOID (p), A68_REF_SIZE);
  85      *DEREF (A68_REF, &ref_new) = new_row;
  86      REF_SCOPE (&ref_new) = scope;
  87      PUSH_REF (p, ref_new);
  88    } else {
  89      PUSH_OBJECT (p, new_row, A68_ROW);
  90    }
  91    PROP_T self;
  92    UNIT (&self) = genie_diagonal_function;
  93    SOURCE (&self) = p;
  94    return self;
  95  }
  96  
  97  //! @brief Push description for transpose of matrix.
  98  
  99  PROP_T genie_transpose_function (NODE_T * p)
 100  {
 101    NODE_T *q = SUB (p);
 102    BOOL_T name = (BOOL_T) (IS_REF (MOID (p)));
 103    MOID_T *m = (name ? SUB_MOID (NEXT (q)) : MOID (NEXT (q)));
 104    GENIE_UNIT (NEXT (q));
 105    ADDR_T scope = PRIMAL_SCOPE;
 106    if (name) {
 107      A68_REF z;
 108      POP_REF (p, &z);
 109      CHECK_REF (p, z, MOID (SUB (p)));
 110      scope = REF_SCOPE (&z);
 111      PUSH_REF (p, *DEREF (A68_REF, &z));
 112    }
 113    A68_ROW row; A68_ARRAY *arr; A68_TUPLE *tup1, *tup2;
 114    POP_OBJECT (p, &row, A68_ROW);
 115    GET_DESCRIPTOR2 (arr, tup1, tup2, &row);
 116    A68_ROW new_row = heap_generator (p, m, DESCRIPTOR_SIZE (2));
 117    A68_ARRAY new_arr = *arr;
 118    A68_TUPLE new_tup1 = *tup2, new_tup2 = *tup1;
 119    PUT_DESCRIPTOR2 (new_arr, new_tup1, new_tup2, &new_row);
 120    if (name) {
 121      A68_REF ref_new = heap_generator (p, MOID (p), A68_REF_SIZE);
 122      *DEREF (A68_REF, &ref_new) = new_row;
 123      REF_SCOPE (&ref_new) = scope;
 124      PUSH_REF (p, ref_new);
 125    } else {
 126      PUSH_OBJECT (p, new_row, A68_ROW);
 127    }
 128    PROP_T self;
 129    UNIT (&self) = genie_transpose_function;
 130    SOURCE (&self) = p;
 131    return self;
 132  }
 133  
 134  //! @brief Push description for row vector.
 135  
 136  PROP_T genie_row_function (NODE_T * p)
 137  {
 138    NODE_T *q = SUB (p);
 139    ADDR_T scope = PRIMAL_SCOPE;
 140    BOOL_T name = (BOOL_T) (IS_REF (MOID (p)));
 141    int k = 1;
 142    if (IS (q, TERTIARY)) {
 143      A68_INT x;
 144      GENIE_UNIT (q);
 145      POP_OBJECT (p, &x, A68_INT);
 146      k = VALUE (&x);
 147      FORWARD (q);
 148    }
 149    GENIE_UNIT (NEXT (q));
 150    MOID_T *m = (name ? SUB_MOID (NEXT (q)) : MOID (NEXT (q)));
 151    if (name) {
 152      A68_REF z;
 153      POP_REF (p, &z);
 154      CHECK_REF (p, z, MOID (SUB (p)));
 155      scope = REF_SCOPE (&z);
 156      PUSH_REF (p, *DEREF (A68_REF, &z));
 157    }
 158    A68_ROW row; A68_ARRAY *arr; A68_TUPLE *tup;
 159    POP_OBJECT (p, &row, A68_ROW);
 160    GET_DESCRIPTOR (arr, tup, &row);
 161    if (DIM (arr) != 1) {
 162      diagnostic (A68_RUNTIME_ERROR, p, ERROR_NO_VECTOR, m, PRIMARY);
 163      exit_genie (p, A68_RUNTIME_ERROR);
 164    }
 165    m = (name ? SUB_MOID (p) : MOID (p));
 166    A68_ROW new_row = heap_generator (p, m, DESCRIPTOR_SIZE (2));
 167    A68_ARRAY new_arr;
 168    DIM (&new_arr) = 2;
 169    MOID (&new_arr) = m;
 170    ELEM_SIZE (&new_arr) = ELEM_SIZE (arr);
 171    SLICE_OFFSET (&new_arr) = SLICE_OFFSET (arr);
 172    FIELD_OFFSET (&new_arr) = FIELD_OFFSET (arr);
 173    ARRAY (&new_arr) = ARRAY (arr);
 174    A68_TUPLE tup1, tup2;
 175    LWB (&tup1) = k;
 176    UPB (&tup1) = k;
 177    SPAN (&tup1) = 1;
 178    SHIFT (&tup1) = k * SPAN (&tup1);
 179    K (&tup1) = 0;
 180    LWB (&tup2) = 1;
 181    UPB (&tup2) = ROW_SIZE (tup);
 182    SPAN (&tup2) = SPAN (tup);
 183    SHIFT (&tup2) = SPAN (tup);
 184    K (&tup2) = 0;
 185    PUT_DESCRIPTOR2 (new_arr, tup1, tup2, &new_row);
 186    if (name) {
 187      A68_REF ref_new = heap_generator (p, MOID (p), A68_REF_SIZE);
 188      *DEREF (A68_REF, &ref_new) = new_row;
 189      REF_SCOPE (&ref_new) = scope;
 190      PUSH_REF (p, ref_new);
 191    } else {
 192      PUSH_OBJECT (p, new_row, A68_ROW);
 193    }
 194    PROP_T self;
 195    UNIT (&self) = genie_row_function;
 196    SOURCE (&self) = p;
 197    return self;
 198  }
 199  
 200  //! @brief Push description for column vector.
 201  
 202  PROP_T genie_column_function (NODE_T * p)
 203  {
 204    NODE_T *q = SUB (p);
 205    BOOL_T name = (BOOL_T) (IS_REF (MOID (p)));
 206    ADDR_T scope = PRIMAL_SCOPE;
 207    int k = 1;
 208    if (IS (q, TERTIARY)) {
 209      A68_INT x;
 210      GENIE_UNIT (q);
 211      POP_OBJECT (p, &x, A68_INT);
 212      k = VALUE (&x);
 213      FORWARD (q);
 214    }
 215    GENIE_UNIT (NEXT (q));
 216    if (name) {
 217      A68_REF z;
 218      POP_REF (p, &z);
 219      CHECK_REF (p, z, MOID (SUB (p)));
 220      scope = REF_SCOPE (&z);
 221      PUSH_REF (p, *DEREF (A68_REF, &z));
 222    }
 223    A68_ROW row; A68_ARRAY *arr; A68_TUPLE *tup;
 224    POP_OBJECT (p, &row, A68_ROW);
 225    GET_DESCRIPTOR (arr, tup, &row);
 226    MOID_T *m = (name ? SUB_MOID (p) : MOID (p));
 227    A68_ROW new_row = heap_generator (p, m, DESCRIPTOR_SIZE (2));
 228    A68_ARRAY new_arr;
 229    DIM (&new_arr) = 2;
 230    MOID (&new_arr) = m;
 231    ELEM_SIZE (&new_arr) = ELEM_SIZE (arr);
 232    SLICE_OFFSET (&new_arr) = SLICE_OFFSET (arr);
 233    FIELD_OFFSET (&new_arr) = FIELD_OFFSET (arr);
 234    ARRAY (&new_arr) = ARRAY (arr);
 235    A68_TUPLE tup1, tup2;
 236    LWB (&tup1) = 1;
 237    UPB (&tup1) = ROW_SIZE (tup);
 238    SPAN (&tup1) = SPAN (tup);
 239    SHIFT (&tup1) = SPAN (tup);
 240    K (&tup1) = 0;
 241    LWB (&tup2) = k;
 242    UPB (&tup2) = k;
 243    SPAN (&tup2) = 1;
 244    SHIFT (&tup2) = k * SPAN (&tup2);
 245    K (&tup2) = 0;
 246    PUT_DESCRIPTOR2 (new_arr, tup1, tup2, &new_row);
 247    if (name) {
 248      A68_REF ref_new = heap_generator (p, MOID (p), A68_REF_SIZE);
 249      *DEREF (A68_REF, &ref_new) = new_row;
 250      REF_SCOPE (&ref_new) = scope;
 251      PUSH_REF (p, ref_new);
 252    } else {
 253      PUSH_OBJECT (p, new_row, A68_ROW);
 254    }
 255    PROP_T self;
 256    UNIT (&self) = genie_column_function;
 257    SOURCE (&self) = p;
 258    return self;
 259  }