
    }Gj@                     \    d dl Z G d d      Zd Zd Zd Zd Zd Zd	 Zd
 Z	d Z
d Zd Zy)    Nc                   F    e Zd ZdZdZd Zd Zed        Zed        Z	d Z
y)	RANArraya  
    Array-valued Rational-Addition Number: elementwise a/b + c, where
    a, b, c are numpy arrays (or broadcastable). Same algebra as the
    scalar RAN(a,b,c) class, but every operation acts on the whole
    array at once via numpy instead of looping over Python RAN objects
    one scalar at a time. Collapse is still only performed where the
    original code performed it (relu's sign check, softmax boundary).
    abcc                     t        j                  |t         j                        | _        t        j                  |t         j                        | _        t        j                  |t         j                        | _        y N)dtype)npasarrayfloat64r   r   r   )selfr   r   r   s       @/home/per/Documents/rational-addition-number-system/ran_array.py__init__zRANArray.__init__   sD    ARZZ0ARZZ0ARZZ0    c                 N    | j                   | j                  z  | j                  z   S Nr   r   s    r   collapsezRANArray.collapse   s    vv''r   c                     t        | j                  j                  | j                  j                  | j                  j                        S r   )r   r   Tr   r   r   s    r   r   z
RANArray.T   s)    $&&((DFFHH55r   c                     t        j                  | j                  | j                  | j                        j
                  S r   )r   	broadcastr   r   r   shaper   s    r   r   zRANArray.shape   s'    ||DFFDFFDFF3999r   c                 "    d| j                    dS )NzRANArray(shape=))r   r   s    r   __repr__zRANArray.__repr__   s     A..r   N)__name__
__module____qualname____doc__	__slots__r   r   propertyr   r   r    r   r   r   r      sE      I1
( 6 6 : :/r   r   c                     | j                   |j                  z  | j                  |j                   z  z   }| j                  |j                  z  }| j                  |j                  z   }t        |||      S r   )r   r   r   r   xyr   r   r   s        r   ran_addr*   '   sU    	acc	ACC!##IA	acc	A	acc	AAq!r   c                 \    t        | j                   | j                  | j                         S r   )r   r   r   r   )r(   s    r   ran_negr,   .   s!    QSSD!##t$$r   c                 ,    t        | t        |            S r   )r*   r,   )r(   r)   s     r   ran_subr.   2   s    1gaj!!r   c                 N   | j                   |j                   z  | j                   |j                  z  |j                  z  z   | j                  | j                  z  |j                   z  z   }| j                  |j                  z  }| j                  |j                  z  }t        |||      S r   )r   r   r   r   r'   s        r   ran_mulr0   6   sv    	acc	ACC!##IO#accACCi!##o5A	acc	A	acc	AAq!r   c                     t        j                  | t         j                        }t        |t        j                  |      t        j
                  |            S r
   )r   r   r   r   	ones_like
zeros_likevaluevs     r   	const_ranr7   E   s6    


5

+AAr||Aa(899r   c                     t        j                  | t         j                        }t        t        j                  |      t        j
                  |      |      S r
   )r   r   r   r   r3   r2   r4   s     r   real_ranr9   J   s6    


5

+ABMM!$bll1oq99r   c                     t        j                  | t         j                        }t        |t        j                  |      |j                               S r
   )r   zerosr   r   r2   copy)r   zs     r   zero_ranr>   O   s3    
bjj)AAr||A11r   c                 V   t        j                  | |d      } t        j                  ||d      }t        j                  ||d      }| j                  d   dkD  r| j                  d   }|dz  }| d | |d | |d | }}}| |d|z   ||d|z   ||d|z   }}
}	||
z  ||	z  z   }||
z  }||z   }|dz  dk(  rTt        j                  || dd  gd      }t        j                  ||dd  gd      }t        j                  ||dd  gd      }|||}}} | j                  d   dkD  r| d   |d   |d   fS )Nr         axis)r   moveaxisr   concatenate)r   r   r   rD   nhalfa1b1c1a2b2c2nanbncs                  r   _tree_reduce_addrR   [   s`   
AtQA
AtQA
AtQA
''!*q.GGAJAvuXq$x5DBtAH%qa$h'74D9IB"WrBw"W"Wq5A:QrsV15BQrsV15BQrsV15Bb"a1 ''!*q. Q41qtr   c                    t        j                  | j                  dk(        rt        j                  |j                  dk(        r| j                  |j                  z  | j                  |j                  z  z   | j                  |j                  z  z   }| j                  |j                  z  }t        j
                  | j                  j                  d   |j                  j                  d   f      }t        |||      S | j                  dddddf   }| j                  dddddf   }| j                  dddddf   }|j                  dddddf   }|j                  dddddf   }	|j                  dddddf   }
||z  ||
z  |	z  z   ||z  |z  z   }||	z  }||
z  }t        |||d      \  }}}t        |||      S )a  
    x: RANArray, components shaped (N, D)
    w: RANArray, components shaped (D, H)
    returns: RANArray, components shaped (N, H)
    Equivalent to sum_d ran_mul(x[:, d], w[d, :]), i.e. a RAN-space
    matrix product where each individual term is still formed with the
    real RAN multiply/add formulas (no rounding is done early).

    Fast path: in this network b is provably 1 for every RAN value at
    every step (weights/biases are built as RAN(v,1,0) or RAN(0,1,0),
    inputs as RAN(0,1,x), and __truediv__ -- the only op that changes
    b -- is never used). With b == e == 1 everywhere, the general
    ran_mul/ran_add reduction collapses algebraically to two ordinary
    linear sums, which lets us use BLAS matmuls instead of a
    Python-level reduction -- same exact numbers, much faster. If that
    invariant is ever broken (e.g. division gets introduced), we fall
    back to the general, slower tree reduction so results stay correct
    either way.
    r@   r   NrC   )	r   allr   r   r   onesr   r   rR   )r(   wr   r   r   xaxbxcwawbwcpapbpcs                 r   
ran_matmulr`   p   sw   ( 
vvaccQhBFF133!8, CC!##Iacc	!ACC!##I-CC!##IGGQSSYYq\13399Q<011a  	
Q4ZB	
Q4ZB	
Q4ZB	
T1aZB	
T1aZB	
T1aZB	b27R<	"r'B,	.B	bB	bBr2r2GAq!Aq!r   c                    t        j                  | j                  dk(        rut        t        j                  | j
                  d      t        j                  | j
                  j                  d         t        j                  | j                  d            S t        | j
                  | j                  | j                  d      \  }}}t        |||      S )zSum a RANArray along axis 0 (used for bias gradients). Same
    fast-path reasoning as ran_matmul: with b == 1 throughout, RAN
    addition of a column is just np.sum on `a` and on `c` separately.r@   r   rC   )
r   rT   r   r   sumr   rU   r   r   rR   )r(   r   r   r   s       r   ran_sum0rc      s     
vvaccQhqss+RWWQSSYYq\-BBFF133UVDWXXqssACC15GAq!Aq!r   )numpyr   r   r*   r,   r.   r0   r7   r9   r>   rR   r`   rc   r%   r   r   <module>re      sF    / /F%":
:
2*&Rr   