2018-12-21 10:26:37 +00:00
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# Distributed under terms of the MIT license.
from decimal import Decimal
from functools import total_ordering
from . exceptions import MOError
from . mo import Atom
from . . coroutine import coroutine , STOOOP
__all__ = [ " moify " , " MOnumber " , " MOstr " ]
2019-05-14 04:55:56 +00:00
2019-05-16 15:17:59 +00:00
def moify ( token ) :
try :
return MOnumber ( token )
except MOError :
pass
try :
return MOstr ( token )
except MOError :
return token
2018-12-21 10:26:37 +00:00
@coroutine
2019-05-16 15:17:59 +00:00
def moify_cor ( target ) :
2018-12-21 10:26:37 +00:00
""" Coroutine which try to convert a parsed token into an MO
: example :
>> > from . . str2 import list_sink
2019-05-16 15:17:59 +00:00
>> > list2molist = moify_cor ( list_sink )
2018-12-21 10:26:37 +00:00
>> > for i in [ - 2 , " + " , " x " , " * " , Decimal ( " 3.3 " ) ] :
. . . list2molist . send ( i )
>> > list2molist . throw ( STOOOP )
[ < MOnumber - 2 > , ' + ' , < MOstr x > , ' * ' , < MOnumber 3.3 > ]
"""
try :
target_ = target ( )
except TypeError :
target_ = target
try :
while True :
tok = yield
2019-05-16 15:17:59 +00:00
target_ . send ( moify ( tok ) )
2018-12-21 10:26:37 +00:00
except STOOOP as err :
yield target_ . throw ( err )
2019-05-14 04:55:56 +00:00
2018-12-21 10:26:37 +00:00
@total_ordering
class MOnumber ( Atom ) :
""" Base number math object (int or Decimal)
: example :
>> > x = MOnumber ( 2 )
>> > x
< MOnumber 2 >
>> > print ( x )
2
>> > x . __txt__
' 2 '
>> > x . __tex__
' 2 '
"""
def __init__ ( self , value ) :
""" Initiate a number MO
: example :
>> > MOnumber ( 23 )
< MOnumber 23 >
>> > MOnumber ( - 23 )
< MOnumber - 23 >
As expected there will be trouble with float
>> > MOnumber ( 23.3 )
< MOnumber 23.300000000000000710542735760100185871124267578125 >
It will be better to use Decimal
>> > MOnumber ( Decimal ( " 23.3 " ) )
< MOnumber 23.3 >
>> > MOnumber ( Decimal ( " -23.3 " ) )
< MOnumber - 23.3 >
2019-07-17 07:25:12 +00:00
Or directly passe a decimal string
>> > MOnumber ( " 23.3 " )
< MOnumber 23.3 >
>> > MOnumber ( " -23.3 " )
< MOnumber - 23.3 >
2018-12-21 10:26:37 +00:00
MOnumber initialisation is idempotent
>> > a = MOnumber ( 23 )
>> > MOnumber ( a )
< MOnumber 23 >
>> > MOnumber ( " a " )
Traceback ( most recent call last ) :
. . .
2019-07-17 07:25:12 +00:00
mapytex . calculus . core . MO . exceptions . MOError : ( ' The value of an MOnumber need to be a int, a float, a Decimal or a decimal string ' , " (got <class ' str ' >) " )
2018-12-21 10:26:37 +00:00
Atoms specific property and methods
>> > print ( a )
23
>> > a . value
23
>> > a . __txt__
' 23 '
>> > a . __tex__
' 23 '
>> > a . _signature
' scalar '
"""
if isinstance ( value , Atom ) and isinstance ( value . value , ( int , Decimal , float ) ) :
Atom . __init__ ( self , value . value )
2019-07-17 07:49:50 +00:00
elif isinstance ( value , ( float , Decimal ) ) :
if int ( value ) == value :
Atom . __init__ ( self , int ( value ) )
else :
Atom . __init__ ( self , Decimal ( value ) )
elif isinstance ( value , int ) :
2018-12-21 10:26:37 +00:00
Atom . __init__ ( self , value )
else :
2019-07-17 07:25:12 +00:00
try :
2019-07-17 07:53:03 +00:00
v = float ( value )
2019-07-17 07:25:12 +00:00
except ( ValueError , TypeError ) :
raise MOError (
" The value of an MOnumber need to be a int, a float, a Decimal or a decimal string " ,
f " (got { type ( value ) } ) " ,
)
else :
2019-07-17 07:53:03 +00:00
if int ( v ) == v :
Atom . __init__ ( self , int ( v ) )
else :
Atom . __init__ ( self , Decimal ( value ) )
2018-12-21 10:26:37 +00:00
self . _signature = " scalar "
@property
def __txt__ ( self ) :
""" Txt rendering
: example :
>> > MOnumber ( 3 ) . __txt__
' 3 '
>> > MOnumber ( - 3 ) . __txt__
' - 3 '
"""
if self . value > = 0 :
return str ( self . value )
return f " - { abs ( self . value ) } "
@property
def __tex__ ( self ) :
""" Tex rendering
: example :
>> > MOnumber ( 3 ) . __tex__
' 3 '
>> > MOnumber ( - 3 ) . __tex__
' - 3 '
"""
2019-07-17 07:49:50 +00:00
if self . value > = 0 :
2018-12-21 10:26:37 +00:00
return str ( self . value )
return f " - { abs ( self . value ) } "
def __lt__ ( self , other ) :
""" < a MOnumber """
try :
return self . value < other . value
except AttributeError :
return self . value < other
2019-07-15 15:48:59 +00:00
def differentiate ( self ) :
""" differentiate a number and get 0
: example :
>> > a = MOnumber ( 3 )
>> > a . differentiate ( )
< MOnumber 0 >
"""
return MOnumber ( 0 )
2018-12-21 10:26:37 +00:00
class MOstr ( Atom ) :
""" Unknown math object like x or n
: example :
>> > x = MOstr ( ' x ' )
>> > x
< MOstr x >
>> > print ( x )
x
>> > x . __txt__
' x '
>> > x . __tex__
' x '
Polynoms properties
>> > x . variable
' x '
>> > x . coefficients
{ 1 : < MOnumber 1 > }
>> > x . degree
1
"""
def __init__ ( self , value ) :
""" Initiate a string MO
>> > a = MOstr ( " x " )
>> > a
< MOstr x >
>> > b = MOstr ( a )
>> > b
< MOstr x >
>> > a = MOstr ( " + " )
Traceback ( most recent call last ) :
. . .
mapytex . calculus . core . MO . exceptions . MOError : An MOstr should be initiate with a alpha string , got +
>> > MOstr ( " ui " )
Traceback ( most recent call last ) :
. . .
mapytex . calculus . core . MO . exceptions . MOError : An MOstr should be initiate with a single caracter string , got ui
>> > MOstr ( 2 )
Traceback ( most recent call last ) :
. . .
mapytex . calculus . core . MO . exceptions . MOError : An MOstr should be initiate with a string - the unknown , got 2
"""
if isinstance ( value , Atom ) :
val = value . value
else :
val = value
if not isinstance ( val , str ) :
2019-05-14 04:55:56 +00:00
raise MOError (
f " An MOstr should be initiate with a string - the unknown, got { val } "
)
2018-12-21 10:26:37 +00:00
if len ( val ) != 1 :
2019-05-14 04:55:56 +00:00
raise MOError (
f " An MOstr should be initiate with a single caracter string, got { val } "
)
2018-12-21 10:26:37 +00:00
if not val . isalpha ( ) :
raise MOError ( f " An MOstr should be initiate with a alpha string, got { val } " )
Atom . __init__ ( self , val )
self . is_scalar = False
self . _signature = " monome1 "
self . _variable = val
@property
def variable ( self ) :
return self . _variable
@property
def coefficients ( self ) :
""" Dictionnary of coefficients
: example :
>> > p = MOstr ( " x " )
>> > p . coefficients
{ 1 : < MOnumber 1 > }
"""
return { 1 : MOnumber ( 1 ) }
@property
def degree ( self ) :
return 1
2019-07-15 15:48:59 +00:00
def differentiate ( self ) :
""" differentiate a variable and get 1
: example :
>> > a = MOstr ( " x " )
>> > a . differentiate ( )
< MOnumber 1 >
"""
return MOnumber ( 1 )
2018-12-21 10:26:37 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del