/*
    TCFbETable.cpp    June 6, 2004.

    Copyright (C) 2003-2004 CFbE Research Group,
    Software Engineering Laboratory,
    Graduate School of Information Science,
    Nara Institute of Science and Technology,
    All rights reserved.

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, (at your option) or
    any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GNU Emacs; see the file COPYING.  If not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/
//---------------------------------------------------------------------------
#pragma hdrstop

#include "TCFbETable.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
// コンストラクタ（空のテーブルを作成
__fastcall TCFbETable::TCFbETable(void)
{
    this->RowLabelList = new TStringList();
    this->ColumnLabelList = new TStringList();
    this->RowList = new TObjectList();

    this->MaxOfRowList = new TObjectList();
    this->MinOfRowList = new TObjectList();
    this->AverageOfRowList = new TObjectList();
    this->MedianOfRowList = new TObjectList();
    this->StdevOfRowList = new TObjectList();
    this->InversedDistanceOfRowList = new TObjectList();
    this->CachedBaseRowListForID = new TList();
    this->MaxOfColumnList = new TObjectList();
    this->MinOfColumnList = new TObjectList();
    this->AverageOfColumnList = new TObjectList();
    this->MedianOfColumnList = new TObjectList();
    this->StdevOfColumnList = new TObjectList();
    this->InversedDistanceOfColumnList = new TObjectList();
    this->CachedBaseColumnListForID = new TList();
}

//---------------------------------------------------------------------------
// 指定された行列を備えた空テーブルを作成
__fastcall TCFbETable::TCFbETable(TStringList* RowLabelList, TStringList* ColumnLabelList)
{
    this->RowLabelList = new TStringList();
    this->ColumnLabelList = new TStringList();
    this->RowList = new TObjectList();

    this->MaxOfRowList = new TObjectList();
    this->MinOfRowList = new TObjectList();
    this->AverageOfRowList = new TObjectList();
    this->MedianOfRowList = new TObjectList();
    this->StdevOfRowList = new TObjectList();
    this->InversedDistanceOfRowList = new TObjectList();
    this->CachedBaseRowListForID = new TList();
    this->MaxOfColumnList = new TObjectList();
    this->MinOfColumnList = new TObjectList();
    this->AverageOfColumnList = new TObjectList();
    this->MedianOfColumnList = new TObjectList();
    this->StdevOfColumnList = new TObjectList();
    this->InversedDistanceOfColumnList = new TObjectList();
    this->CachedBaseColumnListForID = new TList();

    for (int j = 0; j < ColumnLabelList->Count; j++) {
        this->AddColumn(ColumnLabelList->Strings[j]);
    }

    for (int i = 0; i < RowLabelList->Count; i++) {
        this->AddRow(RowLabelList->Strings[i]);
    }
}

//---------------------------------------------------------------------------
// デストラクタ
__fastcall TCFbETable::~TCFbETable()
{
    delete this->CachedBaseColumnListForID;
    delete this->InversedDistanceOfColumnList;
    delete this->StdevOfColumnList;
    delete this->MedianOfColumnList;
    delete this->AverageOfColumnList;
    delete this->MinOfColumnList;
    delete this->MaxOfColumnList;
    delete this->CachedBaseRowListForID;
    delete this->InversedDistanceOfRowList;
    delete this->StdevOfRowList;
    delete this->MedianOfRowList;
    delete this->AverageOfRowList;
    delete this->MinOfRowList;
    delete this->MaxOfRowList;

    delete this->RowList;
    delete this->ColumnLabelList;
    delete this->RowLabelList;
}

//---------------------------------------------------------------------------
// SourceTable の各要素をコピーする
void __fastcall TCFbETable::Assign(TCFbETable* SourceTable)
{
    // SourceTable の列要素をコピー
    for (int j = 0; j < SourceTable->NumberOfColumns; j++) {
        if (this->NumberOfColumns <= j) {
            this->AddColumn(SourceTable->ColumnLabelList->Strings[j]);
        } else {
            this->ColumnLabelList->Strings[j] = SourceTable->ColumnLabelList->Strings[j];
        }

        ((TCFbECell*)this->MaxOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->MaxOfColumnList->Items[j]);
        ((TCFbECell*)this->MinOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->MinOfColumnList->Items[j]);
        ((TCFbECell*)this->AverageOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->AverageOfColumnList->Items[j]);
        ((TCFbECell*)this->MedianOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->MedianOfColumnList->Items[j]);
        ((TCFbECell*)this->StdevOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->StdevOfColumnList->Items[j]);
        ((TCFbECell*)this->InversedDistanceOfColumnList->Items[j])->Assign((TCFbECell*)SourceTable->InversedDistanceOfColumnList->Items[j]);
        this->CachedBaseColumnListForID->Items[j] = (void*)((int)SourceTable->CachedBaseColumnListForID->Items[j]);
    }

    // 余分な列要素を削除
    while (this->NumberOfColumns > SourceTable->NumberOfColumns) {
        this->DeleteColumn(this->ColumnLabelList->Strings[this->NumberOfColumns - 1]);
    }

    // SourceTable の行要素をコピー
    for (int i = 0; i < SourceTable->NumberOfRows; i++) {
        if (this->NumberOfRows <= i) {
            this->AddRow(SourceTable->RowLabelList->Strings[i]);
        } else {
            this->RowLabelList->Strings[i] = SourceTable->RowLabelList->Strings[i];
        }

        ((TCFbECell*)this->MaxOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->MaxOfRowList->Items[i]);
        ((TCFbECell*)this->MinOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->MinOfRowList->Items[i]);
        ((TCFbECell*)this->AverageOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->AverageOfRowList->Items[i]);
        ((TCFbECell*)this->MedianOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->MedianOfRowList->Items[i]);
        ((TCFbECell*)this->StdevOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->StdevOfRowList->Items[i]);
        ((TCFbECell*)this->InversedDistanceOfRowList->Items[i])->Assign((TCFbECell*)SourceTable->InversedDistanceOfRowList->Items[i]);
        this->CachedBaseRowListForID->Items[i] = (void*)((int)SourceTable->CachedBaseRowListForID->Items[i]);
    }

    // 余分な行要素を削除
    while (this->NumberOfRows > SourceTable->NumberOfRows) {
        this->DeleteRow(this->RowLabelList->Strings[this->NumberOfRows - 1]);
    }

    // 行列要素の値を全てコピー
    for (int i = 0; i < this->NumberOfRows; i++) {
        for (int j = 0; j < this->NumberOfColumns; j++) {
            this->CellsByIndex[i][j]->Assign(SourceTable->CellsByIndex[i][j]);
        }
    }
}

//---------------------------------------------------------------------------
// SourceTable の各要素の行と列を入替えてコピーする
void __fastcall TCFbETable::AssignWithTurn(TCFbETable* SourceTable) {
    // SourceTable の行要素を列要素としてコピー
    for (int i = 0; i < SourceTable->NumberOfRows; i++) {
        if (this->NumberOfColumns <= i) {
            this->AddColumn(SourceTable->RowLabelList->Strings[i]);
        } else {
            this->ColumnLabelList->Strings[i] = SourceTable->RowLabelList->Strings[i];
        }

        ((TCFbECell*)this->MaxOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->MaxOfRowList->Items[i]);
        ((TCFbECell*)this->MinOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->MinOfRowList->Items[i]);
        ((TCFbECell*)this->AverageOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->AverageOfRowList->Items[i]);
        ((TCFbECell*)this->MedianOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->MedianOfRowList->Items[i]);
        ((TCFbECell*)this->StdevOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->StdevOfRowList->Items[i]);
        ((TCFbECell*)this->InversedDistanceOfColumnList->Items[i])->Assign((TCFbECell*)SourceTable->InversedDistanceOfRowList->Items[i]);
        this->CachedBaseColumnListForID->Items[i] = (void*)((int)SourceTable->CachedBaseRowListForID->Items[i]);
    }

    // 余分な列要素を削除
    while (this->NumberOfColumns > SourceTable->NumberOfRows) {
        this->DeleteColumn(this->ColumnLabelList->Strings[this->NumberOfColumns - 1]);
    }


    // SourceTable の列要素を行要素としてコピー
    for (int j = 0; j < SourceTable->NumberOfColumns; j++) {
        if (this->NumberOfRows <= j) {
            this->AddRow(SourceTable->ColumnLabelList->Strings[j]);
        } else {
            this->RowLabelList->Strings[j] = SourceTable->ColumnLabelList->Strings[j];
        }

        for (int i = 0; i < this->NumberOfColumns; i++) {
            this->CellsByIndex[j][i]->Assign(SourceTable->CellsByIndex[i][j]);
        }

        ((TCFbECell*)this->MaxOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->MaxOfColumnList->Items[j]);
        ((TCFbECell*)this->MinOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->MinOfColumnList->Items[j]);
        ((TCFbECell*)this->AverageOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->AverageOfColumnList->Items[j]);
        ((TCFbECell*)this->MedianOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->MedianOfColumnList->Items[j]);
        ((TCFbECell*)this->StdevOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->StdevOfColumnList->Items[j]);
        ((TCFbECell*)this->InversedDistanceOfRowList->Items[j])->Assign((TCFbECell*)SourceTable->InversedDistanceOfColumnList->Items[j]);
        this->CachedBaseRowListForID->Items[j] = (void*)((int)SourceTable->CachedBaseColumnListForID->Items[j]);
    }

    // 余分な列要素を削除
    while (this->NumberOfRows > SourceTable->NumberOfColumns) {
        this->DeleteRow(this->RowLabelList->Strings[this->NumberOfRows - 1]);
    }
}

//---------------------------------------------------------------------------
// Table の要素を Normalize する
void __fastcall TCFbETable::Normalize(void)
{
    for (int j = 0; j < this->NumberOfColumns; j++) {
        double Denominator;
        try {
            Denominator = this->GetMaxOfColumn(j) - this->GetMinOfColumn(j);
        } catch (...) {    // 列に enabled な要素がない
            continue;    // 次の列へ
        }                                             
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                if (TCFbEToolkit::GetToolkit()->Equals(Denominator, 0)) {
                    CurrentCell->Value = 0.0;
                } else {
                    CurrentCell->Value = (CurrentCell->Value - this->GetMinOfColumn(j)) / Denominator;
                }
            }
        }

        this->ColumnIsUpdated(j);
    }

    for (int i = 0; i < this->NumberOfRows; i++) {
        this->RowIsUpdated(i);
    }
}

//---------------------------------------------------------------------------
// Table の要素を Standardize する
void __fastcall TCFbETable::Standardize(void)
{
    for (int j = 0; j < this->NumberOfColumns; j++) {
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                if (TCFbEToolkit::GetToolkit()->Equals(this->GetStdevOfColumn(j), 0)) {
                    CurrentCell->Value = 0.0;
                } else {
                    CurrentCell->Value = (CurrentCell->Value - this->GetAverageOfColumn(j)) / this->GetStdevOfColumn(j);
                }
            }
        }

        this->ColumnIsUpdated(j);
    }

    for (int i = 0; i < this->NumberOfRows; i++) {
        this->RowIsUpdated(i);
    }
}

//---------------------------------------------------------------------------
// Table の要素を Ordering する
void __fastcall TCFbETable::Ordering(void)
{
    TList* SortedCellList = new TList();
    for (int j = 0; j < this->NumberOfColumns; j++) {
        this->GetSortedCellListOfColumn(j, SortedCellList);

        int i = 0;
        while (i < SortedCellList->Count) {
            int EqualsCount = 0;
            while (((i+EqualsCount < SortedCellList->Count))
                && (((TCFbECell*)SortedCellList->Items[i])->Value == ((TCFbECell*)SortedCellList->Items[i+EqualsCount])->Value)) {
                EqualsCount++;
            }

            int IndexCount = i;

            for (int k = 0; k < EqualsCount; k++) {
                ((TCFbECell*)SortedCellList->Items[i])->Value = (SortedCellList->Count - (IndexCount + 1 + (EqualsCount - 1) * 0.5)) / (SortedCellList->Count - 1);
                i++;
            }
        }

        this->ColumnIsUpdated(j);
    }

    for (int i = 0; i < this->NumberOfRows; i++) {
        this->RowIsUpdated(i);
    }
    delete SortedCellList;
}

//---------------------------------------------------------------------------
// Table の要素を横方向に Normalize する
void __fastcall TCFbETable::RowNormalize(void)
{
    for (int i = 0; i < this->NumberOfRows; i++) {
        double Denominator = this->GetMaxOfRow(i) - this->GetMinOfRow(i);
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                if (TCFbEToolkit::GetToolkit()->Equals(Denominator, 0)) {
                    CurrentCell->Value = 0.0;
                } else {
                    CurrentCell->Value = (CurrentCell->Value - this->GetMinOfRow(i)) / Denominator;
                }
            }
        }

        this->RowIsUpdated(i);
    }

    for (int j = 0; j < this->NumberOfColumns; j++) {
        this->ColumnIsUpdated(j);
    }
}

//---------------------------------------------------------------------------
// Table の要素を横方向に Standardize する
void __fastcall TCFbETable::RowStandardize(void)
{
    for (int i = 0; i < this->NumberOfRows; i++) {
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                if (TCFbEToolkit::GetToolkit()->Equals(this->GetStdevOfRow(i), 0)) {
                    CurrentCell->Value = 0.0;
                } else {
                    CurrentCell->Value = (CurrentCell->Value - this->GetAverageOfRow(i)) / this->GetStdevOfRow(i);
                }
            }
        }

        this->RowIsUpdated(i);
    }

    for (int j = 0; j < this->NumberOfColumns; j++) {
        this->ColumnIsUpdated(j);
    }
}

//---------------------------------------------------------------------------
// Table の要素を横方向に Ordering する
void __fastcall TCFbETable::RowOrdering(void)
{
    TList* SortedCellList = new TList();
    for (int i = 0; i < this->NumberOfRows; i++) {
        this->GetSortedCellListOfRow(i, SortedCellList);

        int j = 0;
        while (j < SortedCellList->Count) {
            int EqualsCount = 0;
            while (((j+EqualsCount < SortedCellList->Count))
                && (((TCFbECell*)SortedCellList->Items[j])->Value == ((TCFbECell*)SortedCellList->Items[j+EqualsCount])->Value)) {
                EqualsCount++;
            }

            int IndexCount = j;

            for (int k = 0; k < EqualsCount; k++) {
                ((TCFbECell*)SortedCellList->Items[j])->Value = (SortedCellList->Count - (IndexCount + 1 + (EqualsCount - 1) * 0.5)) / (SortedCellList->Count - 1);
                j++;
            }
        }

        this->ColumnIsUpdated(i);
    }

    for (int j = 0; j < this->NumberOfRows; j++) {
        this->ColumnIsUpdated(j);
    }
    delete SortedCellList;
}

//---------------------------------------------------------------------------
// TargetRowIndex 行 TargetColumnIndex 列目のNormalize された値 Value を DisNormalize して返す
double __fastcall TCFbETable::DisNormalize(int ColumnIndex, double NormalizedValue)
{
    return NormalizedValue * (this->GetMaxOfColumn(ColumnIndex) - this->GetMinOfColumn(ColumnIndex)) + this->GetMinOfColumn(ColumnIndex);
}

//---------------------------------------------------------------------------
// ColumnIndex 列目の Standardize された値 StandardizedValue を DisNormalize して返す
double __fastcall TCFbETable::DisStandardize(int ColumnIndex, double StandardizedValue)
{
    return StandardizedValue * this->GetStdevOfColumn(ColumnIndex) + this->GetAverageOfColumn(ColumnIndex);
}

//---------------------------------------------------------------------------
// ColumnIndex 列目の Ordering された値 Order を DisOrdering して返す
double __fastcall TCFbETable::DisOrdering(int ColumnIndex, double Order, TDoubleDynArray& SortedOrders)
{
    TDoubleDynArray SortedValues;
    this->GetEnabledCellsInColumn(ColumnIndex, SortedValues);
    return this->DisOrderingCommon(ColumnIndex, Order, SortedOrders, SortedValues);
}

//---------------------------------------------------------------------------
// RowIndex 列目の横方向に Normalize された値 RowNormalizedValue を DisRowNormalize して返す
double __fastcall TCFbETable::DisRowNormalize(int RowIndex, double RowNormalizedValue)
{
    return RowNormalizedValue * (this->GetMaxOfRow(RowIndex) - this->GetMinOfRow(RowIndex)) + this->GetMinOfRow(RowIndex);
}

//---------------------------------------------------------------------------
// RowIndex 列目の横方向に Standardize された値 RowStandardizedValue を DisRowStandardize して返す
double __fastcall TCFbETable::DisRowStandardize(int RowIndex, double RowStandardizedValue)
{
    return RowStandardizedValue * this->GetStdevOfRow(RowIndex) + this->GetAverageOfRow(RowIndex);
}

//---------------------------------------------------------------------------
// RowIndex 列目の横方向に Ordering された値 RowOrder を DisRowOrdering して返す
double __fastcall TCFbETable::DisRowOrdering(int RowIndex, double RowOrder, TDoubleDynArray& SortedOrders)
{
    TDoubleDynArray SortedValues;
    this->GetEnabledCellsInRow(RowIndex, SortedValues);
    double result = this->DisOrderingCommon(RowIndex, RowOrder, SortedOrders, SortedValues);
    return result;
}

//---------------------------------------------------------------------------
// DisOrdering と DisRowOrdering で使う共通の処理
double __fastcall TCFbETable::DisOrderingCommon(int Index, double Order, TDoubleDynArray& SortedOrders, TDoubleDynArray& SortedValues)
{
    TCFbEToolkit::GetToolkit()->SortDoubleDynArray(SortedValues, sdDescending);    // 降順ソート

    if (SortedValues.Length != SortedOrders.Length) {
        SortedValues.Length = 0;
        throw Exception("SortedValues.Length differed from SortedOrders.Length (in TCFbETable::DisRowOrdering).");
    }

    if (SortedOrders.Length <= 0) {
        throw Exception("There is no elememt in SortedOrders (in TCFbETable::DisRowOrdering).");
    }

    // 既存のいずれかのメトリクスの中に，予測値と同じものがある場合
    for (int i = 0; i < SortedOrders.Length; i++) {
        if (TCFbEToolkit::GetToolkit()->Equals(SortedOrders[i], Order)) {
            double ReturnValue = SortedValues[i];
            SortedValues.Length = 0;
            return ReturnValue;
        }
    }

    double LowestOrder = SortedOrders[SortedOrders.High];
    double HighestOrder = SortedOrders[0];

    // orderOf(pa,j) < orderOf(mlowest,j)である場合
    if (Order < LowestOrder) {
        int i = SortedOrders.High;
        while (--i > 0) {
            if (SortedOrders[i] > LowestOrder) {
                break;
            }
        }

        double SecondLowestOrder = (i >= 0) ? SortedOrders[i] : HighestOrder;    // RowIndex 列目の値の中で2番目に小さいもの
        double LowestValue = SortedValues[SortedValues.High];

        if (TCFbEToolkit::GetToolkit()->Equals(SecondLowestOrder - LowestOrder, 0.0)) {
            SortedValues.Length = 0;
            return LowestValue * (Order - LowestOrder) + LowestValue;
        }

        double SecondLowestValue = SortedValues[i];
        SortedValues.Length = 0;

        return (SecondLowestValue - LowestValue) / (SecondLowestOrder - LowestOrder) * (Order - LowestOrder) + LowestValue;

    // (2) orderOf(pa,j) > orderOf(mhighest,j)である場合
    } else if (Order > HighestOrder) {
        int i = 0;
        while (++i < SortedOrders.Length) {
            if (SortedOrders[i] < HighestOrder) {
                break;
            }
        }

        double SecondHighestOrder = (i >= 0) ? SortedOrders[i] : LowestOrder;    // RowIndex 列目の値の中で2番目に大きいもの
        double HighestValue = SortedValues[0];

        if (TCFbEToolkit::GetToolkit()->Equals(HighestOrder - SecondHighestOrder, 0.0)) {
            SortedValues.Length = 0;
            return HighestValue * (Order - HighestOrder) + HighestValue;
        }

        double SecondHighestValue = SortedValues[i];
        SortedValues.Length = 0;

        return (HighestValue - SecondHighestValue) / (HighestOrder - SecondHighestOrder) * (Order - HighestOrder) + HighestValue;
    }

    // それ以外の場合
    int    HighIndex = 0;
    int    LowIndex = SortedOrders.High;

    for (int i = 0; i < SortedOrders.Length; i++) {
        double CurrentOrder = SortedOrders[i];
        if ((CurrentOrder < Order) && (CurrentOrder > SortedOrders[LowIndex])) {
            LowIndex = i;
        } else if ((CurrentOrder > Order) && (CurrentOrder < SortedOrders[HighIndex])) {
            HighIndex = i;
        }
    }

    double HighOrder    = SortedOrders[HighIndex];
    double LowOrder    = SortedOrders[LowIndex];
    double HighValue    = SortedValues[HighIndex];
    double LowValue    = SortedValues[LowIndex];
    SortedValues.Length = 0;

    if (TCFbEToolkit::GetToolkit()->Equals(HighOrder - LowOrder, 0.0)) {
        return LowValue * (Order - LowOrder) + LowValue;
    }

    return ((HighValue - LowValue) / (HighOrder - LowOrder)) * (Order - LowOrder) + LowValue;
}

//---------------------------------------------------------------------------
// RowLabel, ColumnLabel のセルの値に Value を加算する
// 指定された行，または，列が存在しないときは，例外が送出される
void __fastcall TCFbETable::AddValue(AnsiString RowLabel, AnsiString ColumnLabel, double Value)
{
    this->CellsByIndex[this->RowIsUpdated(RowLabel)][this->ColumnIsUpdated(ColumnLabel)]->Value += Value;
}

//---------------------------------------------------------------------------
// RowLabel, ColumnLabel のセルの値を Value に更新する
// 指定された行，または，列が存在しないときは，例外が送出される
void __fastcall TCFbETable::UpdateValue(AnsiString RowLabel, AnsiString ColumnLabel, double Value)
{
    this->CellsByIndex[this->RowIsUpdated(RowLabel)][this->ColumnIsUpdated(ColumnLabel)]->Value = Value;
}

//---------------------------------------------------------------------------
// RowLabel, ColumnLabel のセルを削除する（Enabled = false にする
// 指定された行，または，列が存在しないときは，例外が送出される
void __fastcall TCFbETable::DeleteValue(AnsiString RowLabel, AnsiString ColumnLabel)
{
    this->CellsByIndex[this->RowIsUpdated(RowLabel)][this->ColumnIsUpdated(ColumnLabel)]->Enabled = false;
}

//---------------------------------------------------------------------------
// 行を追加する．
// 行が既に存在する場合は例外を送出する．
// 追加した行の添字を返す
int __fastcall TCFbETable::AddRow(AnsiString RowLabel)
{
    if (this->RowLabelList->IndexOf(RowLabel) >= 0) {
        throw Exception("The row named \"" + RowLabel + "\" was already existing.");
    }

    TObjectList* AddedRow = new TObjectList();
    for (int j = 0; j < this->NumberOfColumns ; j++) {
        AddedRow->Add(new TCFbECell);
    }
    this->RowList->Add(AddedRow);

    // キャッシュの追加
    this->MaxOfRowList->Add(new TCFbECell());
    this->MinOfRowList->Add(new TCFbECell());
    this->AverageOfRowList->Add(new TCFbECell());
    this->MedianOfRowList->Add(new TCFbECell());
    this->StdevOfRowList->Add(new TCFbECell());
    this->InversedDistanceOfRowList->Add(new TCFbECell());
    this->CachedBaseRowListForID->Add((void*)-1);

    return this->RowLabelList->Add(RowLabel);
}

//---------------------------------------------------------------------------
// 行を削除する．
// 行が存在しない場合は例外を送出する．
void __fastcall TCFbETable::DeleteRow(AnsiString RowLabel)
{
    int TargetRowIndex = this->RowLabelList->IndexOf(RowLabel);
    if (TargetRowIndex < 0) {
        throw Exception("The row named \"" + RowLabel + "\" was not existing.");
    }
    this->RowLabelList->Delete(TargetRowIndex);

    // キャッシュの削除
    this->MaxOfRowList->Delete(TargetRowIndex);
    this->MinOfRowList->Delete(TargetRowIndex);
    this->AverageOfRowList->Delete(TargetRowIndex);
    this->MedianOfRowList->Delete(TargetRowIndex);
    this->StdevOfRowList->Delete(TargetRowIndex);
    this->InversedDistanceOfRowList->Delete(TargetRowIndex);
    this->CachedBaseRowListForID->Delete(TargetRowIndex);

    this->RowList->Delete(TargetRowIndex);
    return;
}

//---------------------------------------------------------------------------
// 行の各要素を加算する．要素は ColumnLabelList で指定された順に Values に格納される．
// RowLabel に指定された行，または，ColumnLabelList に指定された列が存在しない場合，新たに行，または，列を追加する．
// ColumnLabelList の要素数と Values の要素数が異なる場合，例外を送出する．
void __fastcall TCFbETable::AddRowElements(AnsiString RowLabel, TStringList* ColumnLabelList, TDoubleDynArray& Values)
{
    if (ColumnLabelList->Count != Values.Length) {
        throw EInvalidArgument("There is inconsistency between ColumnLabelList->Count and Values.Length (in TCFbETable::AddRowElements).");
    }

    int TargetRowIndex = this->RowIsUpdated(RowLabel);

    if (TargetRowIndex < 0) {
        TargetRowIndex = this->AddRow(RowLabel);
    }

    for (int j = 0; j < ColumnLabelList->Count; j++) {
        int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabelList->Strings[j]);

        if (TargetColumnIndex < 0) {
            TargetColumnIndex = this->AddColumn(ColumnLabelList->Strings[j]);
        }

        TCFbECell* TargetCell = (TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex];
        if (!TargetCell->Enabled) {
            TargetCell->Value = 0.0;
        }
        TargetCell->Value += Values[j];
    }
}

//---------------------------------------------------------------------------
// 行の各要素を更新する．要素は ColumnLabelList で指定された順に Values に格納される
// RowLabel に指定された行，または，ColumnLabelList に指定された列が存在しない場合，新たに行，または，列を追加する．
// ColumnLabelList の要素数と Values の要素数が異なる場合，例外を送出する．
void __fastcall TCFbETable::UpdateRowElements(AnsiString RowLabel, TStringList* ColumnLabelList, TDoubleDynArray& Values)
{
    if (ColumnLabelList->Count != Values.Length) {
        throw EInvalidArgument("There is inconsistency between ColumnLabelList->Count and Values.Length (in TCFbETable::UpdateRowElements).");
    }

    int TargetRowIndex = this->RowIsUpdated(RowLabel);

    if (TargetRowIndex < 0) {
        TargetRowIndex = this->AddRow(RowLabel);
    }

    for (int j = 0; j < ColumnLabelList->Count; j++) {
        int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabelList->Strings[j]);
        if (TargetColumnIndex < 0) {
            TargetColumnIndex = this->AddColumn(ColumnLabelList->Strings[j]);
        }

        ((TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex])->Value = Values[j];
    }
}

//---------------------------------------------------------------------------
// 行の指定要素の Enabled を false にする．要素は ColumnLabelList で指定される．行自体の削除は行わない．
// RowLabel に指定された行，または，ColumnLabelList に指定された列が存在しない場合，例外を送出する．
void __fastcall TCFbETable::DeleteRowElements(AnsiString RowLabel, TStringList* ColumnLabelList)
{
    int TargetRowIndex = this->RowIsUpdated(RowLabel);

    if (TargetRowIndex < 0) {
        throw EInvalidArgument("The row named \"" + RowLabel + "\" was not existing. (TCFbETable::DeleteRowElements).");
    }

    for (int j = 0; j < ColumnLabelList->Count; j++) {
        int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabelList->Strings[j]);
        if (TargetColumnIndex < 0) {
            throw EInvalidArgument("The column named \"" + ColumnLabelList->Strings[j] + "\" was not existing. (TCFbETable::DeleteRowElements).");
        }

        ((TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex])->Enabled = false;
    }
}

//---------------------------------------------------------------------------
// 列を追加する．
// 列が既に存在する場合は例外を送出する．
// 追加した列の添字を返す．
int __fastcall TCFbETable::AddColumn(AnsiString ColumnLabel)
{
    if (this->ColumnLabelList->IndexOf(ColumnLabel) >= 0) {
        throw Exception("The column named \"" + ColumnLabel + "\" was already existing.");
    }

    for (int i = 0; i < this->NumberOfRows ; i++) {
        ((TObjectList*)this->RowList->Items[i])->Add(new TCFbECell);
    }

    // キャッシュの追加
    this->MaxOfColumnList->Add(new TCFbECell());
    this->MinOfColumnList->Add(new TCFbECell());
    this->AverageOfColumnList->Add(new TCFbECell());
    this->MedianOfColumnList->Add(new TCFbECell());
    this->StdevOfColumnList->Add(new TCFbECell());
    this->InversedDistanceOfColumnList->Add(new TCFbECell());
    this->CachedBaseColumnListForID->Add((void*)-1);

    return this->ColumnLabelList->Add(ColumnLabel);
}

//---------------------------------------------------------------------------
// 列を削除する．
// 列が存在しない場合は例外を送出する．
void __fastcall TCFbETable::DeleteColumn(AnsiString ColumnLabel)
{
    int TargetColumnIndex = this->ColumnLabelList->IndexOf(ColumnLabel);
    if (TargetColumnIndex < 0) {
        throw Exception("The column named \"" + ColumnLabel + "\" was not existing.");
    }

    this->ColumnLabelList->Delete(TargetColumnIndex);

    // キャッシュの削除
    this->MaxOfColumnList->Delete(TargetColumnIndex);
    this->MinOfColumnList->Delete(TargetColumnIndex);
    this->AverageOfColumnList->Delete(TargetColumnIndex);
    this->MedianOfColumnList->Delete(TargetColumnIndex);
    this->StdevOfColumnList->Delete(TargetColumnIndex);
    this->InversedDistanceOfColumnList->Delete(TargetColumnIndex);
    this->CachedBaseColumnListForID->Delete(TargetColumnIndex);

    for (int i = 0; i < this->NumberOfRows ; i++) {
        ((TObjectList*)this->RowList->Items[i])->Delete(TargetColumnIndex);
    }
    return;
}

//---------------------------------------------------------------------------
// 列の各要素を加算する．要素は RowLabelList で指定された順に Values に格納される．
// ColumnLabel に指定された列，または，RowLabelList に指定された行が存在しない場合，新たに列，または，行を追加する．
// RowLabelList の要素数と Values の要素数が異なる場合，例外を送出する．
void __fastcall TCFbETable::AddColumnElements(AnsiString ColumnLabel, TStringList* RowLabelList, TDoubleDynArray& Values)
{
    if (RowLabelList->Count != Values.Length) {
        throw EInvalidArgument("There is inconsistency between RowLabelList->Count and Values.Length (in TCFbETable::AddColumnElements).");
    }

    int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabel);

    if (TargetColumnIndex < 0) {
        TargetColumnIndex = this->AddColumn(ColumnLabel);
    }

    for (int i = 0; i < RowLabelList->Count; i++) {
        int TargetRowIndex = this->RowIsUpdated(RowLabelList->Strings[i]);
        if (TargetRowIndex < 0) {
            TargetRowIndex = this->AddRow(RowLabelList->Strings[i]);
        }

        TCFbECell* TargetCell = (TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex];
        if (!TargetCell->Enabled) {
            TargetCell->Value = 0.0;
        }
        TargetCell->Value += Values[i];
    }
}

//---------------------------------------------------------------------------
// 列の各要素を更新する．要素は RowLabelList で指定された順に Values に格納される．
// ColumnLabel に指定された列，または，RowLabelList に指定された行が存在しない場合，新たに列，または，行を追加する．
// RowLabelList の要素数と Values の要素数が異なる場合，例外を送出する．
void __fastcall TCFbETable::UpdateColumnElements(AnsiString ColumnLabel, TStringList* RowLabelList, TDoubleDynArray& Values)
{
    if (RowLabelList->Count != Values.Length) {
        throw EInvalidArgument("There is inconsistency between RowLabelList->Count and Values.Length (in TCFbETable::UpdateColumnElements).");
    }

    int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabel);

    if (TargetColumnIndex < 0) {
        TargetColumnIndex = this->AddColumn(ColumnLabel);
    }

    for (int i = 0; i < RowLabelList->Count; i++) {
        int TargetRowIndex = this->RowIsUpdated(RowLabelList->Strings[i]);
        if (TargetRowIndex < 0) {
            TargetRowIndex = this->AddRow(RowLabelList->Strings[i]);
        }

        ((TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex])->Value = Values[i];
    }
}

//---------------------------------------------------------------------------
// 列の指定要素の Enabled を false にする．要素は RowLabelList で指定される．列自体の削除は行わない．
// ColumnLabel に指定された列，または，RowLabelList に指定された行が存在しない場合，例外を送出する．
void __fastcall TCFbETable::DeleteColumnElements(AnsiString ColumnLabel, TStringList* RowLabelList)
{
    int TargetColumnIndex = this->ColumnIsUpdated(ColumnLabel);

    if (TargetColumnIndex < 0) {
        throw EInvalidArgument("The column named \"" + ColumnLabel + "\" was not existing. (TCFbETable::DeleteColumnElements).");
    }

    for (int i = 0; i < RowLabelList->Count; i++) {
        int TargetRowIndex = this->RowIsUpdated(RowLabelList->Strings[i]);
        if (TargetRowIndex < 0) {
            throw EInvalidArgument("The row named \"" + RowLabelList->Strings[i] + "\" was not existing. (TCFbETable::DeleteColumnElements).");
        }

        ((TCFbECell*)((TObjectList*)this->RowList->Items[TargetRowIndex])->Items[TargetColumnIndex])->Enabled = false;
    }
}

//---------------------------------------------------------------------------
// 行の最大値を返す．
// 行の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMaxOfRow(int i)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MaxOfRowList->Items[i];

    if (!CachedCell->Enabled) {
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled && (!CachedCell->Enabled || (CurrentCell->Value > CachedCell->Value))) {
                CachedCell->Value = CurrentCell->Value;
            }
        }

        if (!CachedCell->Enabled) {
            throw Exception("There is no elements in the row (in TCFbETable::GetMaxOfRow).");
        }
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 行の最小値を返す．
// 行の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMinOfRow(int i)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MinOfRowList->Items[i];

    if (!CachedCell->Enabled) {
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled && (!CachedCell->Enabled || (CurrentCell->Value < CachedCell->Value))) {
                CachedCell->Value = CurrentCell->Value;
            }
        }

        if (!CachedCell->Enabled) {
            throw Exception("There is no elements in the row (in TCFbETable::GetMinOfRow).");
        }
    }
    
    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 行の平均値を返す．
// 行の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetAverageOfRow(int i)
{
    TCFbECell* CachedCell = (TCFbECell*)this->AverageOfRowList->Items[i];

    if (!CachedCell->Enabled) {
        int Count = 0;
        double Sum = 0;

        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                Sum += CurrentCell->Value;
                Count++;
            }
        }

        if (Count == 0) {
            throw Exception("There is no elements in the row (in TCFbETable::GetAverageOfRow).");
        }

        CachedCell->Value = Sum / Count;
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 行の中間値を返す．
// 行の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMedianOfRow(int i)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MedianOfRowList->Items[i];

    if (!CachedCell->Enabled) {
        TDoubleDynArray EnabledValues;
        this->GetEnabledCellsInRow(i, EnabledValues);

        if (EnabledValues.Length == 0) {
            throw Exception("There is no elements in the row (in TCFbETable::GetMedianOfRow).");
        }

        TCFbEToolkit::GetToolkit()->SortDoubleDynArray(EnabledValues, sdDescending);
        CachedCell->Value = TCFbEToolkit::GetToolkit()->GetMedianOfDynArray(EnabledValues);
        EnabledValues.Length = 0;
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 行の標準偏差を返す．
// 行の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetStdevOfRow(int i)
{
    TCFbECell* CachedCell = (TCFbECell*)this->StdevOfRowList->Items[i];

    if (!CachedCell->Enabled) {
        double Average;
        try {
            Average = this->GetAverageOfRow(i);
        } catch (...) {
            throw Exception("There is no elements in the row (in TCFbETable::GetStdevOfRow).");
        }

        double    Sum = 0.0;
        int    Count = 0;
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                Sum += pow(CurrentCell->Value - Average, 2.0);
                Count++;
            }
        }

        CachedCell->Value = sqrt(Sum / (double)Count);
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// ComparedRowIndex 番目の行の BaseRowIndex 番目の行に対する Inversed Distance を返す．
double __fastcall TCFbETable::GetInversedDistanceOfRow(int BaseRowIndex, int ComparedRowIndex)
{
    if ((int)this->CachedBaseRowListForID->Items[ComparedRowIndex] != BaseRowIndex) {
        double Sum = 0.0;
        int Count = 0;
        for (int j = 0; j < this->NumberOfColumns; j++) {
            TCFbECell* DenominatorOfComparedCell = this->CellsByIndex[ComparedRowIndex][j];
            TCFbECell* DenominatorOfBaseCell = this->CellsByIndex[BaseRowIndex][j];

            if (DenominatorOfComparedCell->Enabled && DenominatorOfBaseCell->Enabled && !TCFbEToolkit::GetToolkit()->Equals(DenominatorOfComparedCell->Value, 0.0) && !TCFbEToolkit::GetToolkit()->Equals(DenominatorOfBaseCell->Value, 0.0)) {
                for (int k = 0; k < this->NumberOfColumns; k++) {
                    TCFbECell* NumeratorOfComparedCell = this->CellsByIndex[ComparedRowIndex][k];
                    TCFbECell* NumeratorOfBaseCell = this->CellsByIndex[BaseRowIndex][k];

                    if (NumeratorOfComparedCell->Enabled && NumeratorOfBaseCell->Enabled && (j != k)) {
                        Sum += sqrt( pow((NumeratorOfComparedCell->Value / DenominatorOfComparedCell->Value) - (NumeratorOfBaseCell->Value / DenominatorOfBaseCell->Value), 2.0));
                        Count++;
                    }
                }
            }
        }

        ((TCFbECell*)this->InversedDistanceOfRowList->Items[ComparedRowIndex])->Value = (Sum == 0.0) ? 0.0 : (double)Count / Sum;

        this->CachedBaseRowListForID->Items[ComparedRowIndex] = (void*)BaseRowIndex;
    }

    return ((TCFbECell*)this->InversedDistanceOfRowList->Items[ComparedRowIndex])->Value;
}

//---------------------------------------------------------------------------
// ComparedRowIndex 番目の行の BaseRowIndex 番目の行に対する Averaged Multiplier を返す．
double __fastcall TCFbETable::GetAveragedMultiplierOfRow(int BaseRowIndex, int ComparedRowIndex)
{
    double    Sum = 0.0;
    int    Count = 0;

    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* ComparedCell = this->CellsByIndex[ComparedRowIndex][j];
        TCFbECell* BaseCell = this->CellsByIndex[BaseRowIndex][j];

        if (ComparedCell->Enabled && BaseCell->Enabled && !TCFbEToolkit::GetToolkit()->Equals(ComparedCell->Value, 0.0)) {
            Sum += fabs(BaseCell->Value / ComparedCell->Value);
            Count++;
        }
    }

    if (Count == 0) {
        return 0.0;
    }

    return Sum / Count;
}

//---------------------------------------------------------------------------
// ComparedRowIndex 番目の行の BaseRowIndex 番目の行に対する Median of Multiplier を返す．
double __fastcall TCFbETable::GetMedianOfMultiplierOfRow(int BaseRowIndex, int ComparedRowIndex)
{
    TDoubleDynArray EnabledValues;

    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* ComparedCell = this->CellsByIndex[ComparedRowIndex][j];
        TCFbECell* BaseCell = this->CellsByIndex[BaseRowIndex][j];

        if (ComparedCell->Enabled && BaseCell->Enabled && !TCFbEToolkit::GetToolkit()->Equals(ComparedCell->Value, 0)) {
            EnabledValues.Length++;
            EnabledValues[EnabledValues.High] = fabs(BaseCell->Value / ComparedCell->Value);
        }
    }

    double ReturnValue = 0.0;
    if (EnabledValues.Length > 0) {
        TCFbEToolkit::GetToolkit()->SortDoubleDynArray(EnabledValues, sdDescending);
        ReturnValue = TCFbEToolkit::GetToolkit()->GetMedianOfDynArray(EnabledValues);
        EnabledValues.Length = 0;
    }

    return ReturnValue;
}

//---------------------------------------------------------------------------
// BaseColumnIndex 番目の列に関する ComparedRowIndex 番目の行の BaseRowIndex 番目の行に対する Weighted Multiplier を返す．
double __fastcall TCFbETable::GetWeightedMultiplierOfRow(int BaseRowIndex, int ComparedRowIndex, int BaseColumnIndex)
{
    double    Numerator = 0.0;
    double    Denominator = 0;

    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* ComparedCell = this->CellsByIndex[ComparedRowIndex][j];
        TCFbECell* BaseCell = this->CellsByIndex[BaseRowIndex][j];

        if (ComparedCell->Enabled && BaseCell->Enabled && !TCFbEToolkit::GetToolkit()->Equals(ComparedCell->Value, 0)) {
            double Weight = this->GetInversedDistanceOfColumn(BaseColumnIndex, j);
            Numerator += fabs(BaseCell->Value / ComparedCell->Value) * Weight;
            Denominator += Weight;
        }
    }

    if (Denominator == 0.0) {
        return 0.0;
    }

    return Numerator / Denominator;
}

//---------------------------------------------------------------------------
// 列で Enabled なセルの数を返す
int    __fastcall TCFbETable::GetEnabledCountOfRow(int i)
{
    int    Count = 0;
    for (int j = 0; j < this->NumberOfColumns; j++) {
        if (((TCFbECell*)this->CellsByIndex[i][j])->Enabled) {
            Count++;
        }
    }
    return    Count;
}
//---------------------------------------------------------------------------
// 列の最大値を返す．
// 列の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMaxOfColumn(int j)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MaxOfColumnList->Items[j];

    if (!CachedCell->Enabled) {
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled && (!CachedCell->Enabled || (CurrentCell->Value > CachedCell->Value))) {
                CachedCell->Value = CurrentCell->Value;
            }
        }

        if (!CachedCell->Enabled) {
            throw Exception("There is no elements in the column (in TCFbETable::GetMaxOfColumn).");
        }
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 列の最小値を返す．
// 列の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMinOfColumn(int j)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MinOfColumnList->Items[j];

    if (!CachedCell->Enabled) {
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled && (!CachedCell->Enabled || (CurrentCell->Value < CachedCell->Value))) {
                CachedCell->Value = CurrentCell->Value;
            }
        }

        if (!CachedCell->Enabled) {
            throw Exception("There is no elements in the column (in TCFbETable::GetMinOfColumn).");
        }
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 列の平均値を返す．
// 列の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetAverageOfColumn(int j)
{
    TCFbECell* CachedCell = (TCFbECell*)this->AverageOfColumnList->Items[j];

    if (!CachedCell->Enabled) {
        int Count = 0;
        double Sum = 0;

        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                Sum += CurrentCell->Value;
                Count++;
            }
        }

        if (Count == 0) {
            throw Exception("There is no elements in the column (in TCFbETable::GetAverageOfColumn).");
        }

        CachedCell->Value = Sum / Count;
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 列の中間値を返す．
// 列の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetMedianOfColumn(int j)
{
    TCFbECell* CachedCell = (TCFbECell*)this->MedianOfColumnList->Items[j];

    if (!CachedCell->Enabled) {
        TDoubleDynArray EnabledValues;
        this->GetEnabledCellsInColumn(j, EnabledValues);

        if (EnabledValues.Length == 0) {
            throw Exception("There is no elements in the column (in TCFbETable::GetMedianOfColumn).");
        }

        TCFbEToolkit::GetToolkit()->SortDoubleDynArray(EnabledValues, sdDescending);
        CachedCell->Value = TCFbEToolkit::GetToolkit()->GetMedianOfDynArray(EnabledValues);
        EnabledValues.Length = 0;
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// 列の標準偏差を返す．
// 列の要素がない場合は例外を送出する．
double __fastcall TCFbETable::GetStdevOfColumn(int j)
{
    TCFbECell* CachedCell = (TCFbECell*)this->StdevOfColumnList->Items[j];

    if (!CachedCell->Enabled) {
        double Average;
        try {
            Average = this->GetAverageOfColumn(j);
        } catch (...) {
            throw Exception("There is no elements in the column (in TCFbETable::GetStdevOfColumn).");
        }

        double    Sum = 0.0;
        int    Count = 0;
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* CurrentCell = this->CellsByIndex[i][j];
            if (CurrentCell->Enabled) {
                Sum += pow(CurrentCell->Value - Average, 2.0);
                Count++;
            }
        }

        CachedCell->Value = sqrt(Sum / (double)Count);
    }

    return CachedCell->Value;
}

//---------------------------------------------------------------------------
// ComparedColumnIndex 番目の列の BaseColumnIndex 番目の列に対する Inversed Distance を返す．
double __fastcall TCFbETable::GetInversedDistanceOfColumn(int BaseColumnIndex, int ComparedColumnIndex)
{
    if ((int)this->CachedBaseColumnListForID->Items[ComparedColumnIndex] != BaseColumnIndex) {
        double Sum = 0.0;
        int Count = 0;
        for (int i = 0; i < this->NumberOfRows; i++) {
            TCFbECell* DenominatorOfComparedCell = this->CellsByIndex[i][ComparedColumnIndex];
            TCFbECell* DenominatorOfBaseCell = this->CellsByIndex[i][BaseColumnIndex];

            if (DenominatorOfComparedCell->Enabled && DenominatorOfBaseCell->Enabled && (DenominatorOfComparedCell->Value != 0.0) && (DenominatorOfBaseCell->Value != 0.0)) {
                for (int k = 0; k < this->NumberOfRows; k++) {
                    TCFbECell* NumeratorOfComparedCell = this->CellsByIndex[k][ComparedColumnIndex];
                    TCFbECell* NumeratorOfBaseCell = this->CellsByIndex[k][BaseColumnIndex];

                    if (NumeratorOfComparedCell->Enabled && NumeratorOfBaseCell->Enabled && (i != k)) {
                        Sum += sqrt( pow((NumeratorOfComparedCell->Value / DenominatorOfComparedCell->Value) - (NumeratorOfBaseCell->Value / DenominatorOfBaseCell->Value), 2.0));
                        Count++;
                    }
                }
            }
        }

        ((TCFbECell*)this->InversedDistanceOfColumnList->Items[ComparedColumnIndex])->Value = (Sum == 0.0) ? 0.0 : (double)Count / Sum;

        this->CachedBaseColumnListForID->Items[ComparedColumnIndex] = (void*)BaseColumnIndex;
    }

    return ((TCFbECell*)this->InversedDistanceOfColumnList->Items[ComparedColumnIndex])->Value;
}

//---------------------------------------------------------------------------
// ComparedColumnIndex 番目の列の BaseColumnIndex 番目の列に対する Averaged Multiplier を返す．
double __fastcall TCFbETable::GetAveragedMultiplierOfColumn(int BaseColumnIndex, int ComparedColumnIndex)
{
    double    Sum = 0.0;
    int    Count = 0;

    for (int i = 0; i < this->NumberOfRows; i++) {
        TCFbECell* ComparedCell = this->CellsByIndex[i][ComparedColumnIndex];
        TCFbECell* BaseCell = this->CellsByIndex[i][BaseColumnIndex];

        if (ComparedCell->Enabled && BaseCell->Enabled && ComparedCell->Value != 0) {
            Sum += fabs(BaseCell->Value / ComparedCell->Value);
            Count++;
        }
    }

    if (Count == 0) {
        return 0.0;
    }

    return Sum / Count;
}

//---------------------------------------------------------------------------
// ComparedColumnIndex 番目の列の BaseColumnIndex 番目の列に対する Median of Multiplier を返す．
double __fastcall TCFbETable::GetMedianOfMultiplierOfColumn(int BaseColumnIndex, int ComparedColumnIndex)
{
    TDoubleDynArray EnabledValues;

    for (int i = 0; i < this->NumberOfRows; i++) {
        TCFbECell* ComparedCell = this->CellsByIndex[i][ComparedColumnIndex];
        TCFbECell* BaseCell = this->CellsByIndex[i][BaseColumnIndex];

        if (ComparedCell->Enabled && BaseCell->Enabled && ComparedCell->Value != 0) {
            EnabledValues.Length++;
            EnabledValues[EnabledValues.High] = fabs(BaseCell->Value / ComparedCell->Value);
        }
    }

    double ReturnValue = 0.0;
    if (EnabledValues.Length > 0) {
        TCFbEToolkit::GetToolkit()->SortDoubleDynArray(EnabledValues, sdDescending);
        ReturnValue = TCFbEToolkit::GetToolkit()->GetMedianOfDynArray(EnabledValues);
        EnabledValues.Length = 0;
    }

    return ReturnValue;
}

//---------------------------------------------------------------------------
// BaseRowIndex 番目の行に関する ComparedColumnIndex 番目の列の BaseColumnIndex 番目の列に対する Weighted Multiplier を返す．
double __fastcall TCFbETable::GetWeightedMultiplierOfColumn(int BaseColumnIndex, int ComparedColumnIndex, int BaseRowIndex)
{
    double    Numerator = 0.0;
    double    Denominator = 0;

    for (int i = 0; i < this->NumberOfRows; i++) {
        TCFbECell* ComparedCell = this->CellsByIndex[i][ComparedColumnIndex];
        TCFbECell* BaseCell = this->CellsByIndex[i][BaseColumnIndex];

        if (ComparedCell->Enabled && BaseCell->Enabled && (ComparedCell->Value != 0)) {
            double Weight = this->GetInversedDistanceOfRow(BaseRowIndex, i);
            Numerator += fabs(BaseCell->Value / ComparedCell->Value) * Weight;
            Denominator += Weight;
        }
    }

    if (Denominator == 0.0) {
        return 0.0;
    }

    return Numerator / Denominator;
}

//---------------------------------------------------------------------------
// 列で Enabled なセルの数を返す
int    __fastcall TCFbETable::GetEnabledCountOfColumn(int j)
{
    int    Count = 0;
    for (int i = 0; i < this->NumberOfRows; i++) {
        if (((TCFbECell*)this->CellsByIndex[i][j])->Enabled) {
            Count++;
        }
    }
    return    Count;
}

//---------------------------------------------------------------------------
// TargetRowIndex 行目と ComparedRowIndex 行目で共通して Enabled な要素をソートし，TargetSortedCellList と　ComparedSortedCellList にそれぞれ入れて返す（RankCorrelation で使われる
void __fastcall TCFbETable::GetBothEnableSortedCellList(int TargetRowIndex, int ComparedRowIndex, TList* TargetSortedCellList, TList* ComparedSortedCellList)
{
    TargetSortedCellList->Clear();
    ComparedSortedCellList->Clear();
    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* TargetCell = this->CellsByIndex[TargetRowIndex][j];
        TCFbECell* ComparedCell = this->CellsByIndex[ComparedRowIndex][j];
        if (TargetCell->Enabled && ComparedCell->Enabled) {
            TargetSortedCellList->Add(TargetCell);
            ComparedSortedCellList->Add(ComparedCell);
        }
    }
    TargetSortedCellList->Sort(CompareCell);
    ComparedSortedCellList->Sort(CompareCell);
}

//---------------------------------------------------------------------------
// 以下，protected method
//---------------------------------------------------------------------------
// Cells プロパティの Get アクセサ
TCFbECell* __fastcall TCFbETable::GetCells(AnsiString RowLabel, AnsiString ColumnLabel)
{
    int IndexOfRow = this->RowLabelList->IndexOf(RowLabel);
    int IndexOfColumn = this->ColumnLabelList->IndexOf(ColumnLabel);
    return this->GetCellsByIndex(IndexOfRow, IndexOfColumn);
}

//---------------------------------------------------------------------------
// Cells プロパティの Set アクセサ
void __fastcall TCFbETable::SetCells(AnsiString RowLabel, AnsiString ColumnLabel, TCFbECell* Cell)
{
    this->SetCellsByIndex(this->RowIsUpdated(RowLabel), this->ColumnIsUpdated(ColumnLabel), Cell);
}

//---------------------------------------------------------------------------
// CellsByIndex の Get アクセサ
TCFbECell* __fastcall TCFbETable::GetCellsByIndex(int RowIndex, int ColumnIndex)
{
    return (TCFbECell*)((TObjectList*)this->RowList->Items[RowIndex])->Items[ColumnIndex];
}

//---------------------------------------------------------------------------
// CellsByIndex の Set アクセサ
void __fastcall TCFbETable::SetCellsByIndex(int RowIndex, int ColumnIndex, TCFbECell* Cell)
{
    this->RowIsUpdated(RowIndex);
    this->ColumnIsUpdated(ColumnIndex);

    TCFbECell* TargetCell = (TCFbECell*)((TObjectList*)this->RowList->Items[RowIndex])->Items[ColumnIndex];

    if (TargetCell != NULL) {
        delete TargetCell;
    }
    ((TObjectList*)this->RowList->Items[RowIndex])->Items[ColumnIndex] = Cell;
}

//---------------------------------------------------------------------------
void __fastcall TCFbETable::RowIsUpdated(int RowIndex)
{
    if (RowIndex >= 0) {
        ((TCFbECell*)this->MaxOfRowList->Items[RowIndex])->Enabled = false;
        ((TCFbECell*)this->MinOfRowList->Items[RowIndex])->Enabled = false;
        ((TCFbECell*)this->AverageOfRowList->Items[RowIndex])->Enabled = false;
        ((TCFbECell*)this->MedianOfRowList->Items[RowIndex])->Enabled = false;
        ((TCFbECell*)this->StdevOfRowList->Items[RowIndex])->Enabled = false;
//        ((TCFbECell*)this->InversedDistanceOfRowList->Items[RowIndex])->Enabled = false;
        for (int i = 0; i < this->CachedBaseRowListForID->Count; i++) {
            if ((int)this->CachedBaseRowListForID->Items[i] == RowIndex) {
                this->CachedBaseRowListForID->Items[i] = (void*)-1;
            }
        }
        this->CachedBaseRowListForID->Items[RowIndex] = (void*)-1;
    }
    return;
}

//---------------------------------------------------------------------------
// 行のアップデートをマークし，関係するキャッシュをクリアする．
// アップデートされた行の添字を返す．
int __fastcall TCFbETable::RowIsUpdated(AnsiString RowLabel)
{
    int RowIndex = this->RowLabelList->IndexOf(RowLabel);
    this->RowIsUpdated(RowIndex);
    return RowIndex;
}

//---------------------------------------------------------------------------
void __fastcall TCFbETable::ColumnIsUpdated(int  ColumnIndex)
{
    if (ColumnIndex >= 0) {
        ((TCFbECell*)this->MaxOfColumnList->Items[ColumnIndex])->Enabled = false;
        ((TCFbECell*)this->MinOfColumnList->Items[ColumnIndex])->Enabled = false;
        ((TCFbECell*)this->AverageOfColumnList->Items[ColumnIndex])->Enabled = false;
        ((TCFbECell*)this->MedianOfColumnList->Items[ColumnIndex])->Enabled = false;
        ((TCFbECell*)this->StdevOfColumnList->Items[ColumnIndex])->Enabled = false;
//        ((TCFbECell*)this->InversedDistanceOfColumnList->Items[ColumnIndex])->Enabled = false;
        for (int j = 0; j < this->CachedBaseColumnListForID->Count; j++) {
            if ((int)this->CachedBaseColumnListForID->Items[j] == ColumnIndex) {
                this->CachedBaseColumnListForID->Items[j] = (void*)-1;
            }
        }
        this->CachedBaseColumnListForID->Items[ColumnIndex] = (void*)-1;
    }
    return;
}

//---------------------------------------------------------------------------
// 列のアップデートをマークし，関係するキャッシュをクリアする．
// アップデートされた列の添字を返す．
int __fastcall TCFbETable::ColumnIsUpdated(AnsiString ColumnLabel)
{
    int ColumnIndex = this->ColumnLabelList->IndexOf(ColumnLabel);
    this->ColumnIsUpdated(ColumnIndex);
    return ColumnIndex;
}

//---------------------------------------------------------------------------
// RowIndex 番目の行の Enabled な要素を DynArray に入れて返す
void __fastcall TCFbETable::GetEnabledCellsInRow(int RowIndex, TDoubleDynArray& DynArray)
{
    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* CurrentCell = this->CellsByIndex[RowIndex][j];
        if (CurrentCell->Enabled) {
            DynArray.Length++;
            DynArray[DynArray.High] = CurrentCell->Value;
        }
    }
}

//---------------------------------------------------------------------------
// ColumnIndex 番目の列の Enabled な要素を DynArray に入れて返す
void __fastcall TCFbETable::GetEnabledCellsInColumn(int ColumnIndex, TDoubleDynArray& DynArray)
{
    for (int i = 0; i < this->NumberOfRows; i++) {
        TCFbECell* CurrentCell = this->CellsByIndex[i][ColumnIndex];
        if (CurrentCell->Enabled) {
            DynArray.Length++;
            DynArray[DynArray.High] = CurrentCell->Value;
        }
    }
}

//---------------------------------------------------------------------------
// RowIndex 番目の列の Enabled な要素をソートし，SortedCellList に入れて返す
void __fastcall TCFbETable::GetSortedCellListOfRow(int RowIndex, TList* SortedCellList)
{
    SortedCellList->Clear();
    for (int j = 0; j < this->NumberOfColumns; j++) {
        TCFbECell* CurrentCell = this->CellsByIndex[RowIndex][j];
        if (CurrentCell->Enabled) {
            SortedCellList->Add(CurrentCell);
        }
    }
    SortedCellList->Sort(CompareCell);
}

//---------------------------------------------------------------------------
// ColumnIndex 番目の列の Enabled な要素をソートし，SortedCellList に入れて返す
void __fastcall TCFbETable::GetSortedCellListOfColumn(int ColumnIndex, TList* SortedCellList)
{
    SortedCellList->Clear();
    for (int i = 0; i < this->NumberOfRows; i++) {
        TCFbECell* CurrentCell = this->CellsByIndex[i][ColumnIndex];
        if (CurrentCell->Enabled) {
            SortedCellList->Add(CurrentCell);
        }
    }
    SortedCellList->Sort(CompareCell);
}

//---------------------------------------------------------------------------

