11using System ;
22using System . Collections . Concurrent ;
3+ using System . Collections . Generic ;
34using System . Globalization ;
5+ using System . Linq ;
6+ using System . Numerics ;
47using System . Text . RegularExpressions ;
58using KScr . Core . Exception ;
69using KScr . Core . Model ;
@@ -10,10 +13,7 @@ namespace KScr.Core.Std;
1013
1114public enum NumericMode
1215{
13- Byte ,
14- Short ,
1516 Int ,
16- Long ,
1717 Float ,
1818 Double
1919}
@@ -22,9 +22,19 @@ public sealed class Numeric : NativeObj
2222{
2323 public static readonly Regex NumberRegex = new ( @"([\d]+(i|l|f|d|s|b)?)([.,]([\d]+)(f|d))?" ) ;
2424
25- public static Numeric Zero ;
25+ public static readonly Numeric Zero = new ( 0 )
26+ {
27+ Mutable = false ,
28+ Bytes = BitConverter . GetBytes ( ( byte ) 0 ) ,
29+ Mode = NumericMode . Int
30+ } ;
2631
27- public static Numeric One ;
32+ public static readonly Numeric One = new ( 1 )
33+ {
34+ Mutable = false ,
35+ Bytes = BitConverter . GetBytes ( ( byte ) 1 ) ,
36+ Mode = NumericMode . Int
37+ } ;
2838
2939 private static readonly ConcurrentDictionary < decimal , Numeric > Cache = new ( ) ;
3040
@@ -38,12 +48,15 @@ internal Numeric(RuntimeBase vm, bool constant = false) : base(vm)
3848 _objId = vm . NextObjId ( ) ;
3949 }
4050
41- public NumericMode Mode { get ; internal set ; } = NumericMode . Short ;
42- public byte [ ] Bytes { get ; internal set ; } = BitConverter . GetBytes ( ( short ) 0 ) ;
43- public byte ByteValue => GetAs < byte > ( ) ;
44- public short ShortValue => GetAs < short > ( ) ;
45- public int IntValue => GetAs < int > ( ) ;
46- public long LongValue => GetAs < long > ( ) ;
51+ public bool Mutable
52+ {
53+ get => ! _constant && _mutable ;
54+ private set => _mutable = value ;
55+ }
56+
57+ public NumericMode Mode { get ; private set ; } = NumericMode . Int ;
58+ public byte [ ] Bytes { get ; private set ; } = BitConverter . GetBytes ( ( short ) 0 ) ;
59+ public IntN IntNValue => GetAs < IntN > ( ) ;
4760 public float FloatValue => GetAs < float > ( ) ;
4861 public double DoubleValue => GetAs < double > ( ) ;
4962 public string StringValue => GetAs < string > ( ) ;
@@ -86,10 +99,7 @@ public override Stack InvokeNative(RuntimeBase vm, Stack stack, string member, p
8699 else delta = ( Constant ( vm , 0.001 ) . Value as Numeric ) ! ;
87100 stack [ StackOutput . Default ] = Mode switch
88101 {
89- NumericMode . Byte => ByteValue == other . ByteValue ,
90- NumericMode . Short => ShortValue == other . ShortValue ,
91102 NumericMode . Int => IntValue == other . IntValue ,
92- NumericMode . Long => LongValue == other . LongValue ,
93103 NumericMode . Float => Math . Abs ( FloatValue - other . FloatValue ) < delta . FloatValue ,
94104 NumericMode . Double => Math . Abs ( DoubleValue - other . DoubleValue ) < delta . DoubleValue ,
95105 _ => throw new ArgumentOutOfRangeException ( )
@@ -110,10 +120,7 @@ public override string GetKey()
110120 {
111121 return Mode switch
112122 {
113- NumericMode . Byte => CreateKey ( LongValue ) ,
114- NumericMode . Short => CreateKey ( LongValue ) ,
115123 NumericMode . Int => CreateKey ( LongValue ) ,
116- NumericMode . Long => CreateKey ( LongValue ) ,
117124 NumericMode . Float => CreateKey ( FloatValue ) ,
118125 NumericMode . Double => CreateKey ( DoubleValue ) ,
119126 _ => throw new ArgumentOutOfRangeException ( )
@@ -728,4 +735,196 @@ public IObjectRef Tan(RuntimeBase vm)
728735 throw new ArgumentOutOfRangeException ( ) ;
729736 }
730737 }
738+ }
739+
740+ public sealed class IntN : IObject
741+ {
742+ public static readonly char [ ] digits = new [ ] {
743+ '0' ,
744+ '1' ,
745+ '2' ,
746+ '3' ,
747+ '4' ,
748+ '5' ,
749+ '6' ,
750+ '7' ,
751+ '8' ,
752+ '9'
753+ } ;
754+ public static readonly char [ ] chars = new [ ] {
755+ 'A' ,
756+ 'B' ,
757+ 'C' ,
758+ 'D' ,
759+ 'E' ,
760+ 'F' ,
761+ 'G' ,
762+ 'H' ,
763+ 'I' ,
764+ 'J' ,
765+ 'K' ,
766+ 'L' ,
767+ 'M' ,
768+ 'N' ,
769+ 'O' ,
770+ 'P' ,
771+ 'Q' ,
772+ 'R' ,
773+ 'S' ,
774+ 'T' ,
775+ 'U' ,
776+ 'V' ,
777+ 'W' ,
778+ 'X' ,
779+ 'Y' ,
780+ 'Z' ,
781+ 'a' ,
782+ 'b' ,
783+ 'c' ,
784+ 'd' ,
785+ 'e' ,
786+ 'f' ,
787+ 'g' ,
788+ 'h' ,
789+ 'i' ,
790+ 'j' ,
791+ 'k' ,
792+ 'l' ,
793+ 'm' ,
794+ 'n' ,
795+ 'o' ,
796+ 'p' ,
797+ 'q' ,
798+ 'r' ,
799+ 's' ,
800+ 't' ,
801+ 'u' ,
802+ 'v' ,
803+ 'w' ,
804+ 'x' ,
805+ 'y' ,
806+ 'z'
807+ } ;
808+
809+ private static readonly Dictionary < int , IClassInstance > _clsInsts = new ( ) ;
810+ private readonly IClassInstance _clsInst ;
811+
812+ public readonly int N ;
813+ public readonly byte [ ] Bytes ;
814+
815+ private byte [ ] Bits
816+ {
817+ get
818+ {
819+ byte [ ] bits = new byte [ N ] ;
820+ for ( int i = 0 ; i < N ; i ++ )
821+ bits [ i ] = ( byte ) ( ( Bytes [ i / 8 ] & ( 1 << i % 8 - 1 ) ) != 0 ? 1 : 0 ) ;
822+ bits = bits . Reverse ( ) . ToArray ( ) ;
823+ return bits ;
824+ }
825+ }
826+
827+ public byte ByteValue
828+ {
829+ get => Bytes [ 0 ] ;
830+ set => Set ( new [ ] { value } ) ;
831+ }
832+
833+ public short ShortValue
834+ {
835+ get => BitConverter . ToInt16 ( Bytes ) ;
836+ set => Set ( BitConverter . GetBytes ( value ) ) ;
837+ }
838+
839+ public int IntValue
840+ {
841+ get => BitConverter . ToInt32 ( Bytes ) ;
842+ set => Set ( BitConverter . GetBytes ( value ) ) ;
843+ }
844+
845+ public long LongValue
846+ {
847+ get => BitConverter . ToInt64 ( Bytes ) ;
848+ set => Set ( BitConverter . GetBytes ( value ) ) ;
849+ }
850+
851+ public BigInteger BitIntValue
852+ {
853+ get => new ( Bytes ) ;
854+ set => Set ( value . ToByteArray ( ) ) ;
855+ }
856+
857+ public string StringValue ( byte radix )
858+ { // todo: inspect
859+ string str = string . Empty ;
860+ if ( radix == 1 )
861+ str = string . Join ( "" , Bits . Select ( x => x . ToString ( ) ) ) ;
862+ else
863+ {
864+ ( int div , int mod ) divmod ( int x , int y ) => ( x / y , x % y ) ;
865+ void add ( int [ ] output , int [ ] input )
866+ {
867+ int carry = 0 ;
868+ for ( int i = 0 ; i < input . Length ; i ++ )
869+ ( carry , output [ i ] ) = divmod ( output [ i ] + input [ i ] + carry , radix ) ;
870+ for ( int i = 0 ; carry > 0 ; i ++ )
871+ ( carry , output [ i ] ) = divmod ( output [ i ] + carry , radix ) ;
872+ }
873+
874+ int [ ] res = new int [ ( int ) Math . Ceiling ( str . Length * Math . Log ( 2 ) / Math . Log ( 10 ) ) ] ,
875+ s = StringValue ( 1 ) . Substring ( 2 ) . Select ( x => ( int ) x ) . ToArray ( ) ;
876+ foreach ( var c in s )
877+ {
878+ add ( res , res ) ;
879+ add ( res , new [ ] { c } ) ;
880+ }
881+
882+ str = string . Join ( "" , res . Reverse ( ) . Select ( x => ( char ) x ) . ToArray ( ) ) ;
883+ }
884+ return radix switch
885+ {
886+ 1 => "0b" + str ,
887+ 16 => "0x" + str ,
888+ _ => ( radix == 10 ? string . Empty : "0_" ) + str
889+ } ;
890+ }
891+
892+ public IntN ( RuntimeBase vm , int n = 32 )
893+ {
894+ if ( n / 8 > chars . Length )
895+ throw new FatalException ( $ "n too large: { n } ({ n / 8 } )") ;
896+ N = n ;
897+ Bytes = new byte [ ( int ) Math . Ceiling ( ( double ) n / 8 ) ] ;
898+ ObjectId = vm . NextObjId ( ) ;
899+ _clsInst = GetClsInst ( vm , n ) ;
900+ }
901+
902+ private void Set ( byte [ ] bytes )
903+ {
904+ if ( bytes . Length > N )
905+ throw new ArgumentOutOfRangeException ( nameof ( bytes . Length ) , bytes . Length , "Set value too large" ) ;
906+ Array . Fill ( Bytes , ( byte ) 0 ) ;
907+ Array . Copy ( bytes , 0 , Bytes , N - bytes . Length , bytes . Length ) ;
908+ }
909+
910+ public long ObjectId { get ; }
911+
912+ public IClassInstance Type => _clsInst ;
913+
914+ public string ToString ( short variant ) => StringValue ( ( byte ) ( variant == 0 ? 10 : variant ) ) ;
915+
916+ public Stack Invoke ( RuntimeBase vm , Stack stack , string member , params IObject ? [ ] args )
917+ {
918+ throw new NotImplementedException ( ) ;
919+ }
920+
921+ public string GetKey ( ) => $ "int<{ N } >: { StringValue ( 16 ) } ";
922+
923+ private IClassInstance GetClsInst ( RuntimeBase vm , int n )
924+ {
925+ if ( _clsInsts . ContainsKey ( n ) )
926+ return _clsInsts [ n ] ;
927+ return _clsInsts [ n ] = Class . IntType . CreateInstance ( vm , Class . IntType ,
928+ new TypeParameter ( N . ToString ( ) , TypeParameterSpecializationType . N ) ) ;
929+ }
731930}
0 commit comments