[不具合?]COMとの浮動小数点数のやり取りNo.09473
fzok4234 さん 21/06/25 10:06
 
毎度お世話になっております。

さて、.Net Framework 4系のCOMを浮動小数点数モードで使用することについてです
が、倍精度浮動小数点数(.NetのSystem.Double型)を
COM側=>秀丸マクロ側の転送は正常に行えるのですが、秀丸マクロ側=>COM側の転送で
は値がおかしくなってしまいます。

具体的には、秀丸マクロ側でsetpropnum文でプロパティを呼び出したりcallmethod文
などの引数に値を指定してメソッドを呼び出すと、
COM側で受け取った値が
    1. 小数点以下が切り詰められる。
    2. 元の値の範囲が符号付32bit整数の範囲を超えているときには0x80000000に相
当する値に化ける。
となってしまっています。

検証コードと実行結果は以下の通りです。

// ------------------------------------------------ FloatCom.dll -----------
-------------------------------------
using System.Runtime.InteropServices ;
using System.Globalization ;
using System.Collections.Generic ;
using System.Collections.ObjectModel ;
using System ;

namespace FloatCom {
    internal static class Converter {
        public static readonly IFormatProvider FormatProvider
            = (IFormatProvider) ( CultureInfo.InvariantCulture )
        ;
        public static Double FromInt32( Int32 @value ) {
            return ( (IConvertible) @value ).ToDouble( FormatProvider ) ;
        }
        public static Double FromInt64( Int64 @value ) {
            return ( (IConvertible) @value ).ToDouble( FormatProvider ) ;
        }
        public static String ToString( Double @value ) {
            return @value.ToString( @"E16" , FormatProvider ) ;
        }
    }
   
    internal static class CommonData {
        public static readonly Double Int32MinValue = Converter.FromInt32( I
nt32.MinValue ) ;
        public static readonly Double Int32MaxValue = Converter.FromInt32( I
nt32.MaxValue ) ;
        public static readonly Double Int64MinValue = Converter.FromInt64( I
nt64.MinValue ) ;
        public static readonly Double Int64MaxValue = Converter.FromInt64( I
nt64.MaxValue ) ;
    }
   
    internal class SampleItem {
        public readonly String Name  = default( String ) ;
        public readonly Double Value = default( Double ) ;
        public SampleItem( String name , Double @value ) {
            this.Name  = name ?? String.Empty ;
            this.Value = @value ;
        }
        public String Format() {
            return Converter.ToString( this.Value ) ;
        }
    }
   
    internal static class Sample {
        private static readonly SampleItem[] items = default( SampleItem[] ) ;
        public static readonly ReadOnlyCollection< SampleItem > Items
            = default( ReadOnlyCollection< SampleItem > )
        ;
        static Sample() {
            items = new SampleItem[] {
                new SampleItem( @"NaN"                , Double.NaN          
            ) ,
                new SampleItem( @"NegativeInfinity"   , Double.NegativeInfin
ity         ) ,
                new SampleItem( @"MinValue"           , Double.MinValue    
            ) ,
                new SampleItem( @"HalfMinValue"       , Double.MinValue / 2.
0D          ) ,
                new SampleItem( @"QuarterMinValue"    , Double.MinValue / 4.
0D          ) ,
                new SampleItem( @"UnderInt64MinValue" , CommonData.Int64MinV
alue * 2.0D ) ,
                new SampleItem( @"Int64MinValue"      , CommonData.Int64MinV
alue        ) ,
                new SampleItem( @"OverInt64MinValue"  , CommonData.Int64MinV
alue / 2.0D ) ,
                new SampleItem( @"UnderInt32MinValue" , CommonData.Int32MinV
alue * 2.0D ) ,
                new SampleItem( @"Int32MinValue"      , CommonData.Int32MinV
alue        ) ,
                new SampleItem( @"OverInt32MinValue"  , CommonData.Int32MinV
alue / 2.0D ) ,
                new SampleItem( @"NegativeTwo"        , -2.0D              
            ) ,
                new SampleItem( @"NegativeOne"        , -1.0D              
            ) ,
                new SampleItem( @"NegativeHalf"       , -0.5D              
            ) ,
                new SampleItem( @"NegativeEpsilon"    , - Double.Epsilon    
            ) ,
                new SampleItem( @"Zero"               , 0.0D                
            ) ,
                new SampleItem( @"PositiveEpsilon"    , Double.Epsilon      
            ) ,
                new SampleItem( @"PositiveHalf"       , 0.5D                
            ) ,
                new SampleItem( @"PositiveOne"        , 1.0D                
            ) ,
                new SampleItem( @"PositiveTwo"        , 2.0D                
            ) ,
                new SampleItem( @"UnderInt32MaxValue" , CommonData.Int32MaxV
alue / 2.0D ) ,
                new SampleItem( @"Int32MaxValue"      , CommonData.Int32MaxV
alue        ) ,
                new SampleItem( @"OverInt32MaxValue"  , CommonData.Int32MaxV
alue * 2.0D ) ,
                new SampleItem( @"UnderInt64MaxValue" , CommonData.Int64MaxV
alue / 2.0D ) ,
                new SampleItem( @"Int64MaxValue"      , CommonData.Int64MaxV
alue        ) ,
                new SampleItem( @"OverInt64MaxValue"  , CommonData.Int64MaxV
alue * 2.0D ) ,
                new SampleItem( @"QuarterMaxValue"    , Double.MaxValue / 4.
0D          ) ,
                new SampleItem( @"HalfMaxValue"       , Double.MaxValue / 2.
0D          ) ,
                new SampleItem( @"MaxValue"           , Double.MaxValue    
            ) ,
                new SampleItem( @"PositiveInfinity"   , Double.PositiveInfin
ity         ) ,
            } ;
            Items = new ReadOnlyCollection< SampleItem >( (IList< SampleItem
 >) items ) ;
        }
    }
   
    [ ComVisible( true ) ]
    [ GuidAttribute( @"1c57955c-dfb0-4fe6-802b-49513fe8bde6" ) ]
    [ InterfaceType( ComInterfaceType.InterfaceIsIUnknown ) ]
    public interface ITest {
        Int32 Count { get ; }
        Int32 Index { get ; set ; }
        String Name { get ; }
        Double Value { get ; }               // COM内の値をマクロに渡す。
        Double GetValue() ;                  // Valueプロパティのメソッド版。
        Double Memory { get ; set ; }        // COM内の変数をマクロから読み
書きする。
        Double GetMemory() ;                 // Memoryプロパティ(get)のメソ
ッド版。
        void SetMemory( Double @value ) ;    // Memoryプロパティ(set)のメソ
ッド版。
        void ClearMemory() ;
        Double Echo( Double @value ) ;       // マクロから受け取った値をオウ
ム返しする。
        String Format() ;                    // COM内の値を文字列に変換する。
        String FormatFrom( Double @value ) ; // マクロから受け取った値を文字
列に変換する。
    }
   
    [ ComVisible( true ) ]
    [ GuidAttribute( @"30080a58-e01f-426a-9743-e923e25ba28f" ) ]
    [ InterfaceType( ComInterfaceType.InterfaceIsIDispatch ) ]
    public interface ITestEvent {}
   
    [ ComVisible( true ) ]
    [ GuidAttribute( @"d71988aa-6e1a-442b-8046-5c9c0295cb01" ) ]
    [ ClassInterface( ClassInterfaceType.AutoDual ) ]
    [ ComSourceInterfaces( typeof( ITestEvent ) ) ]
    public class Test : ITest {
        public Int32 Count { get { return Sample.Items.Count ; } }
        private Int32 index = -1 ;
        public Int32 Index { get { return this.index ; } set { this.index =
value ; } }
        public String Name { get { return Sample.Items[ this.Index ].Name ; } }
        public Double Value { get { return Sample.Items[ this.Index ].Value
 ; } }
        public Double GetValue() { return this.Value ; }
        private Double memory = default( Double ) ;
        public Double Memory { get { return this.memory ; } set { this.memor
y = value ; } }
        public Double GetMemory() { return this.Memory ; }
        public void SetMemory( Double @value ) { this.Memory = @value ; }
        public void ClearMemory() { this.Memory = default( Double ) ; }
        public Double Echo( Double @value ) { return @value ; }
        public String Format() { return Sample.Items[ this.Index ].Format() ; }
        public String FormatFrom( Double @value ) { return Converter.ToStrin
g( @value ) ; }
    }
   
}


// ------------------------------------------------ FloatCom.mac -----------
-------------------------------------
debuginfo 2 ;
#test = createobject( currentmacrodirectory + @"\FloatCom.dll" , @"FloatCom.
Test" ) ;
    #count = getpropnum( #test , @"Count" ) ;
    #index = 0 ;
    while ( #index < #count ) {
        setpropnum #test , @"Index" , #index ;
        call WriteLine @"[" + getpropstr( #test , @"Name" ) + @"]" ;
        setfloatmode 1 ;
            // COM内の値をマクロ側に受け取る。
            #value = getpropnum( #test , @"Value" ) ;
            call WriteNumber @"Value" , #value ;
            // メソッドを使用してCOM内の値をマクロ側に受け取る。
            call WriteNumber @"GetValue" , callmethod_returnnum( #test , @"G
etValue" ) ;
            // 値をマクロ側からCOM内の変数に送る。
            setpropnum #test , @"Memory" , #value ;
            // COM内の変数に送った値をマクロ側に受け取る。
            call WriteNumber @"Memory" , getpropnum( #test , @"Memory" ) ;
            // 値をマクロ側からCOM内の変数に送る(メソッド使用)。
            callmethod #test , @"SetMemory" , #value ;
            // COM内の変数に送った値をマクロ側に受け取る(メソッド使用)。
            call WriteNumber @"GetMemory" , callmethod_returnnum( #test , @"
GetMemory" ) ;
            callmethod #test , @"ClearMemory" ;
            // 値をマクロ側とCOM側との間で往復させる。
            call WriteNumber @"Echo" , callmethod_returnnum( #test , @"Echo"
 , #value ) ;
            // COM内の元の値をCOM側で文字列に変換する。
            call WriteString @"Format" , callmethod_returnstr( #test , @"For
mat" ) ;
            // 値をマクロ側からCOM側に送ってCOM側で文字列に変換する。
            call WriteString @"FormatFrom" , callmethod_returnstr( #test , @
"FormatFrom" , #value ) ;
            #value = 0 ;
        setfloatmode 0 ;
        call WriteLine @"" ;
        #index = #index + 1 ;
    }
releaseobject #test ;
endmacro ;

WriteNumber :
    call WriteString $$1 , str( ##2 ) ;
    return ;

WriteString :
    call WriteLine $$1 + @" = " + $$2 ;
    return ;

WriteLine :
    debuginfo $$1 + "\U0000000A" ;
    return ;


// ------------------------------------------------ 実行結果 ---------------
---------------------------------
[NaN]
Value = -1.#IND
GetValue = -1.#IND
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = NaN
FormatFrom = -2.1474836480000000E+009

[NegativeInfinity]
Value = -1.#INF
GetValue = -1.#INF
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -Infinity
FormatFrom = -2.1474836480000000E+009

[MinValue]
Value = -1.79769313486232E+308
GetValue = -1.79769313486232E+308
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -1.7976931348623157E+308
FormatFrom = -2.1474836480000000E+009

[HalfMinValue]
Value = -8.98846567431158E+307
GetValue = -8.98846567431158E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -8.9884656743115785E+307
FormatFrom = -2.1474836480000000E+009

[QuarterMinValue]
Value = -4.49423283715579E+307
GetValue = -4.49423283715579E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.4942328371557893E+307
FormatFrom = -2.1474836480000000E+009

[UnderInt64MinValue]
Value = -1.84467440737096E+019
GetValue = -1.84467440737096E+019
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -1.8446744073709552E+019
FormatFrom = -2.1474836480000000E+009

[Int64MinValue]
Value = -9.22337203685478E+018
GetValue = -9.22337203685478E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -9.2233720368547758E+018
FormatFrom = -2.1474836480000000E+009

[OverInt64MinValue]
Value = -4.61168601842739E+018
GetValue = -4.61168601842739E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.6116860184273879E+018
FormatFrom = -2.1474836480000000E+009

[UnderInt32MinValue]
Value = -4294967296
GetValue = -4294967296
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -4.2949672960000000E+009
FormatFrom = -2.1474836480000000E+009

[Int32MinValue]
Value = -2147483648
GetValue = -2147483648
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = -2.1474836480000000E+009
FormatFrom = -2.1474836480000000E+009

[OverInt32MinValue]
Value = -1073741824
GetValue = -1073741824
Memory = -1073741824
GetMemory = -1073741824
Echo = -1073741824
Format = -1.0737418240000000E+009
FormatFrom = -1.0737418240000000E+009

[NegativeTwo]
Value = -2
GetValue = -2
Memory = -2
GetMemory = -2
Echo = -2
Format = -2.0000000000000000E+000
FormatFrom = -2.0000000000000000E+000

[NegativeOne]
Value = -1
GetValue = -1
Memory = -1
GetMemory = -1
Echo = -1
Format = -1.0000000000000000E+000
FormatFrom = -1.0000000000000000E+000

[NegativeHalf]
Value = -0.5
GetValue = -0.5
Memory = 0
GetMemory = 0
Echo = 0
Format = -5.0000000000000000E-001
FormatFrom = 0.0000000000000000E+000

[NegativeEpsilon]
Value = -4.94065645841247E-324
GetValue = -4.94065645841247E-324
Memory = 0
GetMemory = 0
Echo = 0
Format = -4.9406564584124654E-324
FormatFrom = 0.0000000000000000E+000

[Zero]
Value = 0
GetValue = 0
Memory = 0
GetMemory = 0
Echo = 0
Format = 0.0000000000000000E+000
FormatFrom = 0.0000000000000000E+000

[PositiveEpsilon]
Value = 4.94065645841247E-324
GetValue = 4.94065645841247E-324
Memory = 0
GetMemory = 0
Echo = 0
Format = 4.9406564584124654E-324
FormatFrom = 0.0000000000000000E+000

[PositiveHalf]
Value = 0.5
GetValue = 0.5
Memory = 0
GetMemory = 0
Echo = 0
Format = 5.0000000000000000E-001
FormatFrom = 0.0000000000000000E+000

[PositiveOne]
Value = 1
GetValue = 1
Memory = 1
GetMemory = 1
Echo = 1
Format = 1.0000000000000000E+000
FormatFrom = 1.0000000000000000E+000

[PositiveTwo]
Value = 2
GetValue = 2
Memory = 2
GetMemory = 2
Echo = 2
Format = 2.0000000000000000E+000
FormatFrom = 2.0000000000000000E+000

[UnderInt32MaxValue]
Value = 1073741823.5
GetValue = 1073741823.5
Memory = 1073741823
GetMemory = 1073741823
Echo = 1073741823
Format = 1.0737418235000000E+009
FormatFrom = 1.0737418230000000E+009

[Int32MaxValue]
Value = 2147483647
GetValue = 2147483647
Memory = 2147483647
GetMemory = 2147483647
Echo = 2147483647
Format = 2.1474836470000000E+009
FormatFrom = 2.1474836470000000E+009

[OverInt32MaxValue]
Value = 4294967294
GetValue = 4294967294
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.2949672940000000E+009
FormatFrom = -2.1474836480000000E+009

[UnderInt64MaxValue]
Value = 4.61168601842739E+018
GetValue = 4.61168601842739E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.6116860184273879E+018
FormatFrom = -2.1474836480000000E+009

[Int64MaxValue]
Value = 9.22337203685478E+018
GetValue = 9.22337203685478E+018
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 9.2233720368547758E+018
FormatFrom = -2.1474836480000000E+009

[OverInt64MaxValue]
Value = 1.84467440737096E+019
GetValue = 1.84467440737096E+019
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 1.8446744073709552E+019
FormatFrom = -2.1474836480000000E+009

[QuarterMaxValue]
Value = 4.49423283715579E+307
GetValue = 4.49423283715579E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 4.4942328371557893E+307
FormatFrom = -2.1474836480000000E+009

[HalfMaxValue]
Value = 8.98846567431158E+307
GetValue = 8.98846567431158E+307
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 8.9884656743115785E+307
FormatFrom = -2.1474836480000000E+009

[MaxValue]
Value = 1.79769313486232E+308
GetValue = 1.79769313486232E+308
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = 1.7976931348623157E+308
FormatFrom = -2.1474836480000000E+009

[PositiveInfinity]
Value = 1.#INF
GetValue = 1.#INF
Memory = -2147483648
GetMemory = -2147483648
Echo = -2147483648
Format = Infinity
FormatFrom = -2.1474836480000000E+009



[ ]
RE:09473 [不具合?]COMとの浮動小数点数のNo.09474
こみやんま さん 21/06/25 13:09
 
現状のCOMの引数は、特別な指示をしない限り、Int32 | String で渡ってきますね。

bool X64MACRO() { return true; }が定義されているクラスなら、
対応の秀丸のマクロ整数が64bit幅を持つならlongで渡ってきます。

(COM側のメソッドの引数をObjectにするとBox化されて渡ってきますので、わかりや
すいかと思います)

[ ]
RE:09473 [不具合?]COMとの浮動小数点数のNo.09476
秀丸担当 さん 21/06/25 13:44
 

COMオブジェクトのパラメータに数値を渡す場合は、32bit整数固定となるのが現時点
の仕様になっています。
V8.98β8からは、64bit版においてはこみやんまさんの言われる通り、COMオブジェク
ト側にX64MACROというメソッドがあって0以外を返したら64bit整数で渡すという方法
も追加されています。
参照:
https://www.maruo.co.jp/turukame/3/x10388_.html
浮動小数点数のまま数値で渡す方法は、現時点では無いです。
将来的にやるとしたら、allowobjparamのような方法か、X64MACROのように特別なメ
ソッドを追加してもらって、それで対応するということも考えられます。

[ ]
RE:09474 [不具合?]COMとの浮動小数点数のNo.09477
fzok4234 さん 21/06/25 14:05
 
> 現状のCOMの引数は、特別な指示をしない限り、Int32 | String で渡ってきますね。
>
> bool X64MACRO() { return true; }が定義されているクラスなら、
> 対応の秀丸のマクロ整数が64bit幅を持つならlongで渡ってきます。
>
> (COM側のメソッドの引数をObjectにするとBox化されて渡ってきますので、わかり
>やすいかと思います)

ご意見ありがとうございます。

確かにマクロヘルプには
> 数値は、パラメータとして渡すときは、32bit版秀丸エディタでも、64bit版秀丸エ
>ディタでも、32bitの数値として渡します。
> 返り値を数値で受け取るときは、ビット幅に関わらず、32bit版秀丸エディタでは3
>2bitの数値に、64bit版秀丸エディタでは
> 64bitの数値に変換して数値変数に格納されます。
と書かれていますが、このような記述だと
    ・専ら整数モード(setfloatmode 0 ;)でこのような制約が存在して浮動小数点数
モード(setfloatmode 0 ;)には制約がない。
と解釈できてしまいます。どうやらヘルプの不備みたいですね。

整数モードに関しては、おっしゃる通りにX64MACRO()メソッドの埋め込みで制約が回
避可能なのですが、浮動小数点数モードで
これを使うと
    ・小数点以下の切り捨て。
    ・符号付64bit整数の範囲外は0x8000000000000000相当値に矯正。
の処理がされた値となってしまって、結局制約の回避ができませんでした。

いずれにせよ、浮動小数点数のやり取りが
    〇 COM => 秀丸マクロ
    × COM <= 秀丸マクロ
の「一方通行」のままで、64bit整数におけるX64MACRO()のような制約回避策が用意
されていないことがどうしても腑に落ちない
状態です。


[ ]
RE:09477 [不具合?]COMとの浮動小数点数のNo.09478
fzok4234 さん 21/06/25 14:10
 
記述に間違いがありました。訂正いたします。

    誤 専ら整数モード(setfloatmode 0 ;)でこのような制約が存在して浮動小数点
数モード(setfloatmode 0 ;)には制約がない。
    正 専ら整数モード(setfloatmode 0 ;)でこのような制約が存在して浮動小数点
数モード(setfloatmode 1 ;)には制約がない。


[ ]
RE:09476 [不具合?]COMとの浮動小数点数のNo.09479
fzok4234 さん 21/06/25 16:23
 
現時点での秀丸エディタの各エディションとマクロの数値のデータ型との関係は、
    A. 32bit 通常版                        : 符号付32bit整数
    B. 32bit 浮動小数点数版 setfloatmode 0 : 符号付32bit整数
    C. 32bit 浮動小数点数版 setfloatmode 1 : 倍精度浮動小数点数
    D. 64bit 通常版                        : 符号付64bit整数
    E. 64bit 浮動小数点数版 setfloatmode 0 : 符号付32bit整数
    F. 64bit 浮動小数点数版 setfloatmode 1 : 倍精度浮動小数点数
となっています。つまり、マクロの数値のデータ型の種類は
    1. 符号付32bit整数    ( int    , System.Int32  など )
    2. 符号付64bit整数    ( long   , System.Int64  など )
    3. 倍精度浮動小数点数 ( double , System.Double など )
の3つとなっていてエディションやsetfloatmodeで切り替わることを意味しています。
この型の違いは秀丸エディタ「だけ」を
通常使用するのであれば、文字数取得などの一部の例外を除けば大きな問題になるこ
とはまずありません。しかし、DLLや
COMなどの秀丸エディタとは異なる外部の処理系との「相互運用」となると、やり取
りするデータ型を厳格に指定しなければ
いけなくなります。

現状では、相互運用のデータ型は各エディションごとに固定されていて明示的に変更
することができません。しかもCOMに至っては
    COM=>マクロ
の流れではCOM側でデータ型の指定ができるが、
    マクロ=>COM
では強制的にintにキャストされる、という「非対称」な状態となっています。


この問題を解消する方法として理想的なのは、
    「int/long/doubleの3つのデータ型を同時に扱える新たなエディションの用意。」
に尽きると思います。具体的には、マクロの数値データの内部型を
    ・IEEE 754 四倍精度浮動小数点数
    ・double-double演算
といった128bitの浮動小数点数にするなど1個の値でint/long/doubleの全範囲をカ
バーできるようにした上で、
    setfloatmode 2 ; // 強制intモード
    setfloatmode 3 ; // 強制longモード
    setfloatmode 4 ; // 強制doubleモード
という感じで数値のデータ型を切り替えられるようにして、この強制モードではDLL
やCOMに渡す数値のデータ型もちゃんと指定したものに
なる、という具合です。もちろん、このような大改造は大変なのは言うまでもないの
で将来の構想として参考程度にご検討いただければ、
と思っています。


[ ]
RE:09479 [不具合?]COMとの浮動小数点数のNo.09480
秀丸担当 さん 21/06/25 17:08
 

COMオブジェクトにパラメータに数値を渡す場合に非対称なのは、受け側の問題で、
あらゆるオブジェクトが自動的に変換してくれたらいいのですが、そういうわけでは
ないのようなので、互換性の面から32bit整数で固定になっています。
setfloatmodeのようなマクロ全体の数値の扱いというより、パラメータを渡すときだ
けの限定的な互換性の問題で、敢えて32bitにしています。

将来的に指定できる方法があったらいいですが、指定はallowobjparamか、COM側で例
えばFLOATMACRO()メソッドとか、個別の指定のほうがいいかもしれません。
マクロ全体については、setfloatmode 2;で常に64bit整数にできたらいいというネタ
もあって、取り組もうとしていたのですが、けっこう難しそうでした。
いろいろ検討します。

現状の浮動小数点数版とX64MACROの組み合わせについては、浮動小数点数版では64bi
t整数が扱えないので、X64MACROというメソッドがあっても32bitのままにするべきで
した。
V8.98においては浮動小数点数版では32bitのままとなるようにします。

[ ]