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}
@@ -26,14 +26,14 @@ public sealed class Numeric : IObject
2626 {
2727 Mutable = false ,
2828 Bytes = BitConverter . GetBytes ( ( byte ) 0 ) ,
29- Mode = NumericMode . Byte
29+ Mode = NumericMode . Int
3030 } ;
3131
3232 public static readonly Numeric One = new ( 1 )
3333 {
3434 Mutable = false ,
3535 Bytes = BitConverter . GetBytes ( ( byte ) 1 ) ,
36- Mode = NumericMode . Byte
36+ Mode = NumericMode . Int
3737 } ;
3838
3939 private static readonly ConcurrentDictionary < decimal , Numeric > Cache = new ( ) ;
@@ -60,12 +60,9 @@ public bool Mutable
6060 private set => _mutable = value ;
6161 }
6262
63- public NumericMode Mode { get ; private set ; } = NumericMode . Short ;
63+ public NumericMode Mode { get ; private set ; } = NumericMode . Int ;
6464 public byte [ ] Bytes { get ; private set ; } = BitConverter . GetBytes ( ( short ) 0 ) ;
65- public byte ByteValue => GetAs < byte > ( ) ;
66- public short ShortValue => GetAs < short > ( ) ;
67- public int IntValue => GetAs < int > ( ) ;
68- public long LongValue => GetAs < long > ( ) ;
65+ public IntN IntNValue => GetAs < IntN > ( ) ;
6966 public float FloatValue => GetAs < float > ( ) ;
7067 public double DoubleValue => GetAs < double > ( ) ;
7168 public string StringValue => GetAs < string > ( ) ;
@@ -111,10 +108,7 @@ public Stack Invoke(RuntimeBase vm, Stack stack, string member, params IObject?[
111108 else delta = ( Constant ( vm , 0.001 ) . Value as Numeric ) ! ;
112109 stack [ StackOutput . Default ] = Mode switch
113110 {
114- NumericMode . Byte => ByteValue == other . ByteValue ,
115- NumericMode . Short => ShortValue == other . ShortValue ,
116111 NumericMode . Int => IntValue == other . IntValue ,
117- NumericMode . Long => LongValue == other . LongValue ,
118112 NumericMode . Float => Math . Abs ( FloatValue - other . FloatValue ) < delta . FloatValue ,
119113 NumericMode . Double => Math . Abs ( DoubleValue - other . DoubleValue ) < delta . DoubleValue ,
120114 _ => throw new ArgumentOutOfRangeException ( )
@@ -135,10 +129,7 @@ public string GetKey()
135129 {
136130 return Mode switch
137131 {
138- NumericMode . Byte => CreateKey ( LongValue ) ,
139- NumericMode . Short => CreateKey ( LongValue ) ,
140132 NumericMode . Int => CreateKey ( LongValue ) ,
141- NumericMode . Long => CreateKey ( LongValue ) ,
142133 NumericMode . Float => CreateKey ( FloatValue ) ,
143134 NumericMode . Double => CreateKey ( DoubleValue ) ,
144135 _ => throw new ArgumentOutOfRangeException ( )
@@ -740,4 +731,196 @@ public IObjectRef Tan(RuntimeBase vm)
740731 throw new ArgumentOutOfRangeException ( ) ;
741732 }
742733 }
734+ }
735+
736+ public sealed class IntN : IObject
737+ {
738+ public static readonly char [ ] digits = new [ ] {
739+ '0' ,
740+ '1' ,
741+ '2' ,
742+ '3' ,
743+ '4' ,
744+ '5' ,
745+ '6' ,
746+ '7' ,
747+ '8' ,
748+ '9'
749+ } ;
750+ public static readonly char [ ] chars = new [ ] {
751+ 'A' ,
752+ 'B' ,
753+ 'C' ,
754+ 'D' ,
755+ 'E' ,
756+ 'F' ,
757+ 'G' ,
758+ 'H' ,
759+ 'I' ,
760+ 'J' ,
761+ 'K' ,
762+ 'L' ,
763+ 'M' ,
764+ 'N' ,
765+ 'O' ,
766+ 'P' ,
767+ 'Q' ,
768+ 'R' ,
769+ 'S' ,
770+ 'T' ,
771+ 'U' ,
772+ 'V' ,
773+ 'W' ,
774+ 'X' ,
775+ 'Y' ,
776+ 'Z' ,
777+ 'a' ,
778+ 'b' ,
779+ 'c' ,
780+ 'd' ,
781+ 'e' ,
782+ 'f' ,
783+ 'g' ,
784+ 'h' ,
785+ 'i' ,
786+ 'j' ,
787+ 'k' ,
788+ 'l' ,
789+ 'm' ,
790+ 'n' ,
791+ 'o' ,
792+ 'p' ,
793+ 'q' ,
794+ 'r' ,
795+ 's' ,
796+ 't' ,
797+ 'u' ,
798+ 'v' ,
799+ 'w' ,
800+ 'x' ,
801+ 'y' ,
802+ 'z'
803+ } ;
804+
805+ private static readonly Dictionary < int , IClassInstance > _clsInsts = new ( ) ;
806+ private readonly IClassInstance _clsInst ;
807+
808+ public readonly int N ;
809+ public readonly byte [ ] Bytes ;
810+
811+ private byte [ ] Bits
812+ {
813+ get
814+ {
815+ byte [ ] bits = new byte [ N ] ;
816+ for ( int i = 0 ; i < N ; i ++ )
817+ bits [ i ] = ( byte ) ( ( Bytes [ i / 8 ] & ( 1 << i % 8 - 1 ) ) != 0 ? 1 : 0 ) ;
818+ bits = bits . Reverse ( ) . ToArray ( ) ;
819+ return bits ;
820+ }
821+ }
822+
823+ public byte ByteValue
824+ {
825+ get => Bytes [ 0 ] ;
826+ set => Set ( new [ ] { value } ) ;
827+ }
828+
829+ public short ShortValue
830+ {
831+ get => BitConverter . ToInt16 ( Bytes ) ;
832+ set => Set ( BitConverter . GetBytes ( value ) ) ;
833+ }
834+
835+ public int IntValue
836+ {
837+ get => BitConverter . ToInt32 ( Bytes ) ;
838+ set => Set ( BitConverter . GetBytes ( value ) ) ;
839+ }
840+
841+ public long LongValue
842+ {
843+ get => BitConverter . ToInt64 ( Bytes ) ;
844+ set => Set ( BitConverter . GetBytes ( value ) ) ;
845+ }
846+
847+ public BigInteger BitIntValue
848+ {
849+ get => new ( Bytes ) ;
850+ set => Set ( value . ToByteArray ( ) ) ;
851+ }
852+
853+ public string StringValue ( byte radix )
854+ { // todo: inspect
855+ string str = string . Empty ;
856+ if ( radix == 1 )
857+ str = string . Join ( "" , Bits . Select ( x => x . ToString ( ) ) ) ;
858+ else
859+ {
860+ ( int div , int mod ) divmod ( int x , int y ) => ( x / y , x % y ) ;
861+ void add ( int [ ] output , int [ ] input )
862+ {
863+ int carry = 0 ;
864+ for ( int i = 0 ; i < input . Length ; i ++ )
865+ ( carry , output [ i ] ) = divmod ( output [ i ] + input [ i ] + carry , radix ) ;
866+ for ( int i = 0 ; carry > 0 ; i ++ )
867+ ( carry , output [ i ] ) = divmod ( output [ i ] + carry , radix ) ;
868+ }
869+
870+ int [ ] res = new int [ ( int ) Math . Ceiling ( str . Length * Math . Log ( 2 ) / Math . Log ( 10 ) ) ] ,
871+ s = StringValue ( 1 ) . Substring ( 2 ) . Select ( x => ( int ) x ) . ToArray ( ) ;
872+ foreach ( var c in s )
873+ {
874+ add ( res , res ) ;
875+ add ( res , new [ ] { c } ) ;
876+ }
877+
878+ str = string . Join ( "" , res . Reverse ( ) . Select ( x => ( char ) x ) . ToArray ( ) ) ;
879+ }
880+ return radix switch
881+ {
882+ 1 => "0b" + str ,
883+ 16 => "0x" + str ,
884+ _ => ( radix == 10 ? string . Empty : "0_" ) + str
885+ } ;
886+ }
887+
888+ public IntN ( RuntimeBase vm , int n = 32 )
889+ {
890+ if ( n / 8 > chars . Length )
891+ throw new FatalException ( $ "n too large: { n } ({ n / 8 } )") ;
892+ N = n ;
893+ Bytes = new byte [ ( int ) Math . Ceiling ( ( double ) n / 8 ) ] ;
894+ ObjectId = vm . NextObjId ( ) ;
895+ _clsInst = GetClsInst ( vm , n ) ;
896+ }
897+
898+ private void Set ( byte [ ] bytes )
899+ {
900+ if ( bytes . Length > N )
901+ throw new ArgumentOutOfRangeException ( nameof ( bytes . Length ) , bytes . Length , "Set value too large" ) ;
902+ Array . Fill ( Bytes , ( byte ) 0 ) ;
903+ Array . Copy ( bytes , 0 , Bytes , N - bytes . Length , bytes . Length ) ;
904+ }
905+
906+ public long ObjectId { get ; }
907+
908+ public IClassInstance Type => _clsInst ;
909+
910+ public string ToString ( short variant ) => StringValue ( ( byte ) ( variant == 0 ? 10 : variant ) ) ;
911+
912+ public Stack Invoke ( RuntimeBase vm , Stack stack , string member , params IObject ? [ ] args )
913+ {
914+ throw new NotImplementedException ( ) ;
915+ }
916+
917+ public string GetKey ( ) => $ "int<{ N } >: { StringValue ( 16 ) } ";
918+
919+ private IClassInstance GetClsInst ( RuntimeBase vm , int n )
920+ {
921+ if ( _clsInsts . ContainsKey ( n ) )
922+ return _clsInsts [ n ] ;
923+ return _clsInsts [ n ] = Class . IntType . CreateInstance ( vm , Class . IntType ,
924+ new TypeParameter ( N . ToString ( ) , TypeParameterSpecializationType . N ) ) ;
925+ }
743926}
0 commit comments