<commit_before>export { BoundsArraySet };

import * as ConvBiasActivation from "../ConvBiasActivation.js";
import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as Weights from "../../Unpacker/Weights.js";
import { ChannelPartInfo } from  "./Depthwise_ChannelPartInfo.js";

/**
 * The element value bounds set for depthwise convolution-bias-activation.
 *
 */
class BoundsArraySet extends ConvBiasActivation.BoundsArraySet {

  /**
   */
  constructor( inputChannelCount, outputChannelCount ) {
    super( inputChannelCount, outputChannelCount );
  }

//!!! ...unfinished... (2022/01/07) What about ( bDepthwise == false )?

//!!! ...unfinished... (2022/01/09)
// Even if ( this.AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ),
// this function should work correctly and BoundsArraySet should result in pass-through input to output.

  /**
   *
   * @param {ConvBiasActivation.BoundsArraySet} previous_ConvBiasActivation_BoundsArraySet
   *   The value bounds set of the previous convolution-bias-activation.
   *
   * @param {Depthwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   *
   * @param {number} channelMultiplier
   *   The channel multiplier of this depthwise operation.
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this depthwise convolution.
   *
   * @param {boolean} bFilter
   *   Whether this depthwise convolution has bias operation. If ( bFilter == true ), this is a depthwise convolution.
   * If ( bFilter == false ), this is an avg/max pooling (i.e. no filters weights).
   *
   * @param {boolean} bBias
   *   Whether this depthwise convolution has bias operation.
   */
  set_all_by_inChannelPartInfoArray(
    previous_ConvBiasActivation_BoundsArraySet, inChannelPartInfoArray,
    channelMultiplier, nActivationId, bFilter, bBias
  ) {

//!!! ...unfinished... (2022/01/10)
// It should be better to use real filter and bias to calculate per channel value bounds. This is especially important for ActivationEscaping.
// Because activation function inputDomainLinear is not wide, using looser value bounds estimation has higher possibility to lost information.
//
// Perhaps, using two-passes in Depthwise.FiltersArray_BiasesArray.init():
//
//   - In the 1st pass, extracting real filter and bias value. At the same time, calculating .afterFilter and .afterBias
//       by these extracted value combined with undoPreviousEscapingScale
//       (i.e. previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ]). Find out
//       .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation.
//
//   - In the 2nd pass, apply doEscapingScale (i.e. .activationEscaping_ScaleArraySet.do.scales[ outChannel ] )
//       to filter and bias value (and also .afterFilter and .afterBias).
//

    // Because they are extracted from Weights which should have been regulated by Weights.Base.ValueBounds.Float32Array_RestrictedClone().
    //
    // Q: Why not use the real filter and bias value (i.e. not the supposed bounds range) directly.
    // A: Their values are unknown when determine value bounds. Even if they are known, their values are pre-scaled (i.e. altered; not original) value.
    const filtersValueBounds = Weights.Base.ValueBounds;
    const biasesValueBounds = Weights.Base.ValueBounds;

//!!! (2022/01/11 Remarked) Moved to parent class.
//    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    // 1. Determine .input
    //
    // Note: Even if avg/max pooling, input value bounds is the same as the previous ooutput value bounds
    this.input.set_all_byBoundsArray( previous_ConvBiasActivation_BoundsArraySet.output );

    // ( inChannelPartIndex == 0 ), lower half channels. (or, all channels)
    // ( inChannelPartIndex == 1 ), higher half channels.
    for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
      let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
      let inChannelBegin = inChannelPartInfo.beginIndex;
      let inChannelEnd = inChannelPartInfo.endIndex;

      let outChannel = inChannelBegin * channelMultiplier;

      for ( let inChannel = inChannelBegin; inChannel < inChannelEnd; ++inChannel ) {

        let undoPreviousEscapingScale = previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ];

        // 2. Determine .afterUndoPreviousActivationEscaping
        this.afterUndoPreviousActivationEscaping.set_one_byBoundsArray( inChannel, this.input, inChannel );
        this.afterUndoPreviousActivationEscaping.multiply_one_byN( inChannel, undoPreviousEscapingScale );

        for ( let outChannelSub = 0; outChannelSub < channelMultiplier; ++outChannelSub, ++outChannel ) {

          // 3. Determine .afterFilter
          this.afterFilter.set_one_byBoundsArray( outChannel, this.afterUndoPreviousActivationEscaping, inChannel );
          if ( bFilter ) {

            if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
              // Do nothing. The value bounds does not change at all because it is just be past through.

            } else { // Non pass-through half channels.
              this.afterFilter
                .multiply_one_byBounds( outChannel, filtersValueBounds )
                .multiply_one_byN( outChannel, this.filterSize );
            }

          } else { // ( !bFilter ). No filters array to be extracted. (i.e. avg/max pooling)
            // Do nothing. The value bounds does not change for avg/max pooling.
          }

          // 4. Determine .afterBias
          this.afterBias.set_one_byBoundsArray( outChannel, this.afterFilter, outChannel );
          if ( bBias ) {

            if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
              // Do nothing. The value bounds does not change at all because it is just be past through.

            } else { // Non pass-through half channels.
              this.afterBias.add_one_byBounds( outChannel, biasesValueBounds ); // Shift the value bounds by the bias bounds.
            }

          } else { // ( !bBias ). No biases array to be extracted.
            // Do nothing. The value bounds does not change since no bias.
          }

//!!! (2022/01/11 Remarked) Moved to parent class.
//
// //!!! ...unfinished... (2022/01/10)
// // Determine .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation, should be moved to parent class.
// // They should be shared with pointwise and depthwise BoundsArraySet.
//
//           {
//             // 5. Determine .activationEscaping_ScaleArraySet
//             {
//               // 5.1 Determine .do
//
//               if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
//
//                 // Since no activation function, no need to escape. (i.e. scale = 1 for no scale)
//                 this.activationEscaping_ScaleArraySet.do.set_one_byN( outChannel, 1 );
//
//               } else {
//
//                 if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
//
//                   // Calculate the scale for escaping bias result from activation function's non-linear domain into linear domain.
//                   //
//                   // Note: This does not work for avg/max pooling.
//                   this.activationEscaping_ScaleArraySet.do.set_one_by_fromLowerUpper_toLowerUpper( outChannel,
//                     this.afterBias.lowers[ outChannel ], this.afterBias.uppers[ outChannel ],
//                     theActivationFunctionInfo.inputDomainLinear.lower, theActivationFunctionInfo.inputDomainLinear.upper
//                   );
//
//                   let doEscapingScale = this.activationEscaping_ScaleArraySet.do.scales[ outChannel ];
//                   tf.util.assert( ( Number.isNaN( doEscapingScale ) == false ),
//                     `Depthwise.FiltersArray_BiasesArray.set_boundsArraySet_by_inChannelPartInfoArray(): `
//                       + `this.activationEscaping_ScaleArraySet.do.scales[ ${outChannel} ] ( ${doEscapingScale} ) `
//                       + `should not be NaN. `
//                       + `Please use activation function (e.g. tanh()) which has both negative and positive parts near origin point.`
//                   );
//
//                 } else { // Non pass-through half channels.
//                   // Since non-pass-through, no need to escape. (i.e. scale = 1 for no scale)
//                   this.activationEscaping_ScaleArraySet.do.set_one_byN( outChannel, 1 );
//                 }
//               }
//
//               // 5.2 Determine .undo (Prepared for the next convolution-bias-activation. Not for this.)
//               this.activationEscaping_ScaleArraySet.undo.set_one_byUndo_ScaleArray(
//                 outChannel, this.activationEscaping_ScaleArraySet.do, outChannel );
//             }
//
//             // 6. Determine .afterActivationEscaping
//             this.afterActivationEscaping
//               .set_one_byBoundsArray( outChannel, this.afterBias, outChannel )
//               .multiply_one_byNs( outChannel, this.activationEscaping_ScaleArraySet.do.scales, outChannel );
//           }
//
//           // 7. Determine .afterActivation
//           {
//             // If no activation function, the output range is determined by .afterActivationEscaping.
//             if ( this.nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
//               this.afterActivation.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel )
//
//             // Otherwise, the activation function dominates the output range.
//             } else {
//               if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels, it is clamped by the output range for linearDomainLinear.
//                 this.afterActivation.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
//
//               } else { // Non pass-through half channels, it is clamped by the output range for the whole input domain.
//                 this.afterActivation.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
//               }
//             }
//           }

        } // outChannelSub, outChannel
      } // inChannel
    } // inChannelPartIndex

    // 5. Determine .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation
    this.set_activationEscaping_afterActivationEscaping_afterActivation_by_afterBias_nActivationId( nActivationId );
  }

}

<commit_msg>Update Depthwise_BoundsArraySet.js<commit_after>export { BoundsArraySet };

import * as ConvBiasActivation from "../ConvBiasActivation.js";
import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as Weights from "../../Unpacker/Weights.js";
import { ChannelPartInfo } from  "./Depthwise_ChannelPartInfo.js";

/**
 * The element value bounds set for depthwise convolution-bias-activation.
 *
 */
class BoundsArraySet extends ConvBiasActivation.BoundsArraySet {

  /**
   */
  constructor( inputChannelCount, outputChannelCount ) {
    super( inputChannelCount, outputChannelCount );
  }

//!!! ...unfinished... (2022/01/07) What about ( bDepthwise == false )?

//!!! ...unfinished... (2022/01/09)
// Even if ( this.AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ),
// this function should work correctly and BoundsArraySet should result in pass-through input to output.

  /**
   *
   * @param {ConvBiasActivation.BoundsArraySet} previous_ConvBiasActivation_BoundsArraySet
   *   The value bounds set of the previous convolution-bias-activation.
   *
   * @param {Depthwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   *
   * @param {number} channelMultiplier
   *   The channel multiplier of this depthwise operation.
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this depthwise convolution.
   *
   * @param {boolean} bFilter
   *   Whether this depthwise convolution has bias operation. If ( bFilter == true ), this is a depthwise convolution.
   * If ( bFilter == false ), this is an avg/max pooling (i.e. no filters weights).
   *
   * @param {boolean} bBias
   *   Whether this depthwise convolution has bias operation.
   */
  set_all_by_inChannelPartInfoArray(
    previous_ConvBiasActivation_BoundsArraySet, inChannelPartInfoArray,
    channelMultiplier, nActivationId, bFilter, bBias
  ) {

//!!! ...unfinished... (2022/01/10)
// It should be better to use real filter and bias to calculate per channel value bounds. This is especially important for ActivationEscaping.
// Because activation function inputDomainLinear is not wide, using looser value bounds estimation has higher possibility to lost information.
//
// Perhaps, using two-passes in Depthwise.FiltersArray_BiasesArray.init():
//
//   - In the 1st pass, extracting real filter and bias value. At the same time, calculating .afterFilter and .afterBias
//       by these extracted value combined with undoPreviousEscapingScale
//       (i.e. previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ]). Find out
//       .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation.
//
//   - In the 2nd pass, apply doEscapingScale (i.e. .activationEscaping_ScaleArraySet.do.scales[ outChannel ] )
//       to filter and bias value (and also .afterFilter and .afterBias).
//

    // Because they are extracted from Weights which should have been regulated by Weights.Base.ValueBounds.Float32Array_RestrictedClone().
    //
    // Q: Why not use the real filter and bias value (i.e. not the supposed bounds range) directly.
    // A: Their values are unknown when determine value bounds. Even if they are known, their values are pre-scaled (i.e. altered; not original) value.
    const filtersValueBounds = Weights.Base.ValueBounds;
    const biasesValueBounds = Weights.Base.ValueBounds;

//!!! (2022/01/11 Remarked) Moved to parent class.
//    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    // 1. Determine .input
    //
    // Note: Even if avg/max pooling, input value bounds is the same as the previous ooutput value bounds
    this.input.set_all_byBoundsArray( previous_ConvBiasActivation_BoundsArraySet.output );

    // ( inChannelPartIndex == 0 ), lower half channels. (or, all channels)
    // ( inChannelPartIndex == 1 ), higher half channels.
    for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
      let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
      let inChannelBegin = inChannelPartInfo.beginIndex;
      let inChannelEnd = inChannelPartInfo.endIndex;

      let outChannel = inChannelBegin * channelMultiplier;

      for ( let inChannel = inChannelBegin; inChannel < inChannelEnd; ++inChannel ) {

        let undoPreviousEscapingScale = previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ];

        // 2. Determine .afterUndoPreviousActivationEscaping
        this.afterUndoPreviousActivationEscaping.set_one_byBoundsArray( inChannel, this.input, inChannel );
        this.afterUndoPreviousActivationEscaping.multiply_one_byN( inChannel, undoPreviousEscapingScale );

        for ( let outChannelSub = 0; outChannelSub < channelMultiplier; ++outChannelSub, ++outChannel ) {

          // 3. Determine .afterFilter
          this.afterFilter.set_one_byBoundsArray( outChannel, this.afterUndoPreviousActivationEscaping, inChannel );
          if ( bFilter ) {

            if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
              // Do nothing. The value bounds does not change at all because it is just be past through.

            } else { // Non pass-through half channels.
              this.afterFilter
                .multiply_one_byBounds( outChannel, filtersValueBounds )
                .multiply_one_byN( outChannel, this.filterSize );
            }

          } else { // ( !bFilter ). No filters array to be extracted. (i.e. avg/max pooling)
            // Do nothing. The value bounds does not change for avg/max pooling.
          }

          // 4. Determine .afterBias
          this.afterBias.set_one_byBoundsArray( outChannel, this.afterFilter, outChannel );
          if ( bBias ) {

            if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
              // Do nothing. The value bounds does not change at all because it is just be past through.

            } else { // Non pass-through half channels.
              this.afterBias.add_one_byBounds( outChannel, biasesValueBounds ); // Shift the value bounds by the bias bounds.
            }

          } else { // ( !bBias ). No biases array to be extracted.
            // Do nothing. The value bounds does not change since no bias.
          }

//!!! (2022/01/11 Remarked) Moved to parent class.
//
// //!!! ...unfinished... (2022/01/10)
// // Determine .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation, should be moved to parent class.
// // They should be shared with pointwise and depthwise BoundsArraySet.
//
//           {
//             // 5. Determine .activationEscaping_ScaleArraySet
//             {
//               // 5.1 Determine .do
//
//               if ( nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
//
//                 // Since no activation function, no need to escape. (i.e. scale = 1 for no scale)
//                 this.activationEscaping_ScaleArraySet.do.set_one_byN( outChannel, 1 );
//
//               } else {
//
//                 if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
//
//                   // Calculate the scale for escaping bias result from activation function's non-linear domain into linear domain.
//                   //
//                   // Note: This does not work for avg/max pooling.
//                   this.activationEscaping_ScaleArraySet.do.set_one_by_fromLowerUpper_toLowerUpper( outChannel,
//                     this.afterBias.lowers[ outChannel ], this.afterBias.uppers[ outChannel ],
//                     theActivationFunctionInfo.inputDomainLinear.lower, theActivationFunctionInfo.inputDomainLinear.upper
//                   );
//
//                   let doEscapingScale = this.activationEscaping_ScaleArraySet.do.scales[ outChannel ];
//                   tf.util.assert( ( Number.isNaN( doEscapingScale ) == false ),
//                     `Depthwise.FiltersArray_BiasesArray.set_boundsArraySet_by_inChannelPartInfoArray(): `
//                       + `this.activationEscaping_ScaleArraySet.do.scales[ ${outChannel} ] ( ${doEscapingScale} ) `
//                       + `should not be NaN. `
//                       + `Please use activation function (e.g. tanh()) which has both negative and positive parts near origin point.`
//                   );
//
//                 } else { // Non pass-through half channels.
//                   // Since non-pass-through, no need to escape. (i.e. scale = 1 for no scale)
//                   this.activationEscaping_ScaleArraySet.do.set_one_byN( outChannel, 1 );
//                 }
//               }
//
//               // 5.2 Determine .undo (Prepared for the next convolution-bias-activation. Not for this.)
//               this.activationEscaping_ScaleArraySet.undo.set_one_byUndo_ScaleArray(
//                 outChannel, this.activationEscaping_ScaleArraySet.do, outChannel );
//             }
//
//             // 6. Determine .afterActivationEscaping
//             this.afterActivationEscaping
//               .set_one_byBoundsArray( outChannel, this.afterBias, outChannel )
//               .multiply_one_byNs( outChannel, this.activationEscaping_ScaleArraySet.do.scales, outChannel );
//           }
//
//           // 7. Determine .afterActivation
//           {
//             // If no activation function, the output range is determined by .afterActivationEscaping.
//             if ( this.nActivationId == ValueDesc.ActivationFunction.Singleton.Ids.NONE ) {
//               this.afterActivation.set_one_byBoundsArray( outChannel, this.afterActivationEscaping, outChannel )
//
////!!! ...unfinished... (2022/01/11)
//// Consider the implementation of .activationEscaping_ScaleArraySet.do.set_one_by_fromLowerUpper_toLowerUpper(),
//// it is not so good no matter using set_one_byXxx() or clamp_one_byXxx() of this.afterActivation.
//
//             // Otherwise, the activation function dominates the output range.
//             } else {
//               if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels, it is clamped by the output range for linearDomainLinear.
//                 this.afterActivation.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRangeLinear );
//
//               } else { // Non pass-through half channels, it is clamped by the output range for the whole input domain.
//                 this.afterActivation.clamp_one_byBounds( outChannel, theActivationFunctionInfo.outputRange );
//               }
//             }
//           }

        } // outChannelSub, outChannel
      } // inChannel
    } // inChannelPartIndex

    // 5. Determine .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation
    this.set_activationEscaping_afterActivationEscaping_afterActivation_by_afterBias_nActivationId( nActivationId );
  }

}

<|endoftext|>


<commit_before>export { BoundsArraySet };

import * as ConvBiasActivation from "../ConvBiasActivation.js";
import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as Weights from "../../Unpacker/Weights.js";
import { ChannelPartInfo } from  "./Pointwise_ChannelPartInfo.js";

/**
 * The element value bounds for pointwise convolution-bias-activation.
 *
 */
class BoundsArraySet extends ConvBiasActivation.BoundsArraySet {

  /**
   */
  constructor( inputChannelCount, outputChannelCount ) {
    super( inputChannelCount, outputChannelCount );
  }

  /**
   * Set this.bPassThrough[] according to inChannelPartInfoArray.
   *
   * @param {Depthwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   */
  set_all_bPassThrough( inChannelPartInfoArray ) {

    for ( let inChannel = 0; inChannel < this.inputChannelCount; ++inChannel ) {
      let outChannel = 0;

      InChannelPartIndexLoop:
      for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
        let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
        let inChannelToBegin = inChannel - inChannelPartInfo.inChannelBegin;

        for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
          if ( outChannel >= this.outputChannelCount )
            break InChannelPartIndexLoop; // Never exceeds the total output channel count.

          if ( ( inChannelToBegin >= 0 ) && ( inChannel < inChannelPartInfo.inChannelEnd ) ) {

            if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
              this.bPassThrough[ outChannel ] = true;

            } else { // Non-pass-through half channels. (i.e. input multiply filter weight.)
              this.bPassThrough[ outChannel ] = false;
            }

          } else {
            // Do nothing. The value bounds does not change for all input channels which is not in range (since these inputs are ignored).
            // (i.e. input multiply 0.)
            this.bPassThrough[ outChannel ] = ???;
          }

        } // outChannelSub, outChannel
      } // inChannelPartIndex
    } // inChannel

  }

//!!! ...unfinished... (2022/01/09)
// Even if ( this.outputChannelCount <= 0 ),
// this function should work correctly and BoundsArraySet should result in pass-through input to output.

  /**
   *
   * @param {ConvBiasActivation.BoundsArraySet} previous_ConvBiasActivation_BoundsArraySet
   *   The value bounds set of the previous convolution-bias-activation.
   *
   * @param {Pointwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this pointwise convolution.
   *
   * @param {boolean} bBias
   *   Whether this pointwise convolution has bias operation.
   */
  set_all_by_inChannelPartInfoArray(
    previous_ConvBiasActivation_BoundsArraySet, inChannelPartInfoArray,
    nActivationId, bBias
  ) {

//!!! ...unfinished... (2022/01/10)
// It should be better to use real filter and bias to calculate per channel value bounds. This is especially important for ActivationEscaping.
// Because activation function inputDomainLinear is not wide, using looser value bounds estimation has higher possibility to lost information.
//
// Perhaps, using two-passes in Pointwise.FiltersArray_BiasesArray.init():
//
//   - In the 1st pass, extracting real filter and bias value. At the same time, calculating .afterFilter and .afterBias
//       by these extracted value combined with undoPreviousEscapingScale
//       (i.e. previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ]). Find out
//       .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation.
//
//   - In the 2nd pass, apply doEscapingScale (i.e. .activationEscaping_ScaleArraySet.do.scales[ outChannel ] )
//       to filter and bias value (and also .afterFilter and .afterBias).
//

    // Because they are extracted from Weights which should have been regulated by Weights.Base.ValueBounds.Float32Array_RestrictedClone().
    //
    // Q: Why not use the real filter and bias value (i.e. not the supposed bounds range) directly.
    // A: Their values are unknown when determine value bounds. Even if they are known, their values are pre-scaled (i.e. altered; not original) value.
    const filtersValueBounds = Weights.Base.ValueBounds;
    const biasesValueBounds = Weights.Base.ValueBounds;

    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    // 1. Determine .input
    this.input.set_all_byBoundsArray( previous_ConvBiasActivation_BoundsArraySet.output );

//!!! ...unfinished... (2022/01/09)
    { // filtersArray
      let tBounds = new FloatValue.Bounds( 0, 0 );

      this.afterFilter.set_all_byN( 0 ); // Initialize .afterFilter for accumulating every output channel by every input channel.

      for ( let inChannel = 0; inChannel < this.inputChannelCount; ++inChannel ) {
        let undoPreviousEscapingScale = previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ];

        // 2. Determine .afterUndoPreviousActivationEscaping
        this.afterUndoPreviousActivationEscaping.set_one_byBoundsArray( inChannel, this.input, inChannel );
        this.afterUndoPreviousActivationEscaping.multiply_one_byN( inChannel, undoPreviousEscapingScale );

        let outChannel = 0;

        InChannelPartIndexLoop:
        for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
          let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
          let inChannelToBegin = inChannel - inChannelPartInfo.inChannelBegin;

          for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
            if ( outChannel >= this.outputChannelCount )
              break InChannelPartIndexLoop; // Never exceeds the total output channel count.

            if ( ( inChannelToBegin >= 0 ) && ( inChannel < inChannelPartInfo.inChannelEnd ) ) {

              if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.

                if ( inChannelToBegin == outChannelSub ) {

                  // The only one filter position (in the pass-through part) has non-zero value. (i.e. input multiply 1.)
                  this.afterFilter.add_one_byBoundsArray( outChannel, this.afterUndoPreviousActivationEscaping, inChannel );

                } else {
                  // Do nothing. All other filter positions (in the pass-through part) are zero. (i.e. input multiply 0.)
                }

              } else { // Non-pass-through half channels. (i.e. input multiply filter weight.)
                tBounds.set_byBoundsArray( this.afterUndoPreviousActivationEscaping, inChannel ).multiply_byBounds( filtersValueBounds );
                this.afterFilter.add_one_byBounds( outChannel, tBounds )
              }

            } else {
              // Do nothing. The value bounds does not change for all input channels which is not in range (since these inputs are ignored).
              // (i.e. input multiply 0.)
            }

            ++filterIndex;

          } // outChannelSub, outChannel
        } // inChannelPartIndex
      } // inChannel
    } // filtersArray

    // 4. Determine .afterBias
    this.afterBias.set_all_byBoundsArray( this.afterFilter );
    if ( bBias ) {
      let outChannel = 0;

      InChannelPartIndexLoop:
      for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
        let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];

        for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
          if ( outChannel >= this.outputChannelCount )
            break InChannelPartIndexLoop; // Never exceeds the total output channel count.

          if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
            // Do nothing. The value bounds does not change at all because it is just be past through.

          } else { // Non-pass-through half channels.
            this.afterBias.add_one_byBounds( outChannel, biasesValueBounds ); // Shift the value bounds by the bias bounds.
          }

        } // outChannelSub, outChannel
      } // inChannelPartIndex

    } else { // ( !bBias )
      // Do nothing. The value bounds does not change since no bias.
    }

//!!! ...unfinished... (2022/01/09)

  }

}

<commit_msg>Update Pointwise_BoundsArraySet.js<commit_after>export { BoundsArraySet };

import * as ConvBiasActivation from "../ConvBiasActivation.js";
import * as FloatValue from "../../Unpacker/FloatValue.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as Weights from "../../Unpacker/Weights.js";
import { ChannelPartInfo } from  "./Pointwise_ChannelPartInfo.js";

/**
 * The element value bounds for pointwise convolution-bias-activation.
 *
 */
class BoundsArraySet extends ConvBiasActivation.BoundsArraySet {

  /**
   */
  constructor( inputChannelCount, outputChannelCount ) {
    super( inputChannelCount, outputChannelCount );
  }

  /**
   * Set this.bPassThrough[] according to inChannelPartInfoArray.
   *
   * @param {Depthwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   */
  set_all_bPassThrough( inChannelPartInfoArray ) {

    let outChannel = 0;

    InChannelPartIndexLoop:
    for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
      let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
      let inChannelToBegin = inChannel - inChannelPartInfo.inChannelBegin;

      for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
        if ( outChannel >= this.outputChannelCount )
          break InChannelPartIndexLoop; // Never exceeds the total output channel count.

        if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
          this.bPassThrough[ outChannel ] = true;

        } else { // Non-pass-through half channels. (i.e. input multiply filter weight.)
          this.bPassThrough[ outChannel ] = false;
        }

      } // outChannelSub, outChannel
    } // inChannelPartIndex

  }

//!!! ...unfinished... (2022/01/09)
// Even if ( this.outputChannelCount <= 0 ),
// this function should work correctly and BoundsArraySet should result in pass-through input to output.

  /**
   *
   * @param {ConvBiasActivation.BoundsArraySet} previous_ConvBiasActivation_BoundsArraySet
   *   The value bounds set of the previous convolution-bias-activation.
   *
   * @param {Pointwise.ChannelPartInfo[]} inChannelPartInfoArray
   *   The input channel range array which describe lower/higher half channels index range.
   *
   * @param {number} nActivationId
   *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx) of this pointwise convolution.
   *
   * @param {boolean} bBias
   *   Whether this pointwise convolution has bias operation.
   */
  set_all_by_inChannelPartInfoArray(
    previous_ConvBiasActivation_BoundsArraySet, inChannelPartInfoArray,
    nActivationId, bBias
  ) {

//!!! ...unfinished... (2022/01/10)
// It should be better to use real filter and bias to calculate per channel value bounds. This is especially important for ActivationEscaping.
// Because activation function inputDomainLinear is not wide, using looser value bounds estimation has higher possibility to lost information.
//
// Perhaps, using two-passes in Pointwise.FiltersArray_BiasesArray.init():
//
//   - In the 1st pass, extracting real filter and bias value. At the same time, calculating .afterFilter and .afterBias
//       by these extracted value combined with undoPreviousEscapingScale
//       (i.e. previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ]). Find out
//       .activationEscaping_ScaleArraySet, .afterActivationEscaping, .afterActivation.
//
//   - In the 2nd pass, apply doEscapingScale (i.e. .activationEscaping_ScaleArraySet.do.scales[ outChannel ] )
//       to filter and bias value (and also .afterFilter and .afterBias).
//

    // Because they are extracted from Weights which should have been regulated by Weights.Base.ValueBounds.Float32Array_RestrictedClone().
    //
    // Q: Why not use the real filter and bias value (i.e. not the supposed bounds range) directly.
    // A: Their values are unknown when determine value bounds. Even if they are known, their values are pre-scaled (i.e. altered; not original) value.
    const filtersValueBounds = Weights.Base.ValueBounds;
    const biasesValueBounds = Weights.Base.ValueBounds;

    let theActivationFunctionInfo = ValueDesc.ActivationFunction.Singleton.getInfoById( nActivationId );

    // 1. Determine .input
    this.input.set_all_byBoundsArray( previous_ConvBiasActivation_BoundsArraySet.output );

//!!! ...unfinished... (2022/01/09)
    { // filtersArray
      let tBounds = new FloatValue.Bounds( 0, 0 );

      this.afterFilter.set_all_byN( 0 ); // Initialize .afterFilter for accumulating every output channel by every input channel.

      for ( let inChannel = 0; inChannel < this.inputChannelCount; ++inChannel ) {
        let undoPreviousEscapingScale = previous_ConvBiasActivation_BoundsArraySet.activationEscaping_ScaleArraySet.undo.scales[ inChannel ];

        // 2. Determine .afterUndoPreviousActivationEscaping
        this.afterUndoPreviousActivationEscaping.set_one_byBoundsArray( inChannel, this.input, inChannel );
        this.afterUndoPreviousActivationEscaping.multiply_one_byN( inChannel, undoPreviousEscapingScale );

        let outChannel = 0;

        InChannelPartIndexLoop:
        for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
          let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];
          let inChannelToBegin = inChannel - inChannelPartInfo.inChannelBegin;

          for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
            if ( outChannel >= this.outputChannelCount )
              break InChannelPartIndexLoop; // Never exceeds the total output channel count.

            if ( ( inChannelToBegin >= 0 ) && ( inChannel < inChannelPartInfo.inChannelEnd ) ) {

              if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.

                if ( inChannelToBegin == outChannelSub ) {

                  // The only one filter position (in the pass-through part) has non-zero value. (i.e. input multiply 1.)
                  this.afterFilter.add_one_byBoundsArray( outChannel, this.afterUndoPreviousActivationEscaping, inChannel );

                } else {
                  // Do nothing. All other filter positions (in the pass-through part) are zero. (i.e. input multiply 0.)
                }

              } else { // Non-pass-through half channels. (i.e. input multiply filter weight.)
                tBounds.set_byBoundsArray( this.afterUndoPreviousActivationEscaping, inChannel ).multiply_byBounds( filtersValueBounds );
                this.afterFilter.add_one_byBounds( outChannel, tBounds )
              }

            } else {
              // Do nothing. The value bounds does not change for all input channels which is not in range (since these inputs are ignored).
              // (i.e. input multiply 0.)
            }

            ++filterIndex;

          } // outChannelSub, outChannel
        } // inChannelPartIndex
      } // inChannel
    } // filtersArray

    // 4. Determine .afterBias
    this.afterBias.set_all_byBoundsArray( this.afterFilter );
    if ( bBias ) {
      let outChannel = 0;

      InChannelPartIndexLoop:
      for ( let inChannelPartIndex = 0; inChannelPartIndex < inChannelPartInfoArray.length; ++inChannelPartIndex ) {
        let inChannelPartInfo = inChannelPartInfoArray[ inChannelPartIndex ];

        for ( let outChannelSub = 0; outChannelSub < inChannelPartInfo.outputChannelCount; ++outChannelSub, ++outChannel ) {
          if ( outChannel >= this.outputChannelCount )
            break InChannelPartIndexLoop; // Never exceeds the total output channel count.

          if ( inChannelPartInfo.bPassThrough ) { // For pass-through half channels.
            // Do nothing. The value bounds does not change at all because it is just be past through.

          } else { // Non-pass-through half channels.
            this.afterBias.add_one_byBounds( outChannel, biasesValueBounds ); // Shift the value bounds by the bias bounds.
          }

        } // outChannelSub, outChannel
      } // inChannelPartIndex

    } else { // ( !bBias )
      // Do nothing. The value bounds does not change since no bias.
    }

//!!! ...unfinished... (2022/01/09)

  }

}

<|endoftext|>


<commit_before>export { testCorrectness };

import * as RandTools from "../util/RandTools.js";
import * as TensorTools from "../util/TensorTools.js";
import * as FloatValue from "../Unpacker/FloatValue.js";

/**
 * Test ScaleTranslate.
 */
class Base {

  constructor() {
    this.asserter_Equal = new TensorTools.Asserter_Equal();
  }

  assert_PropertyProperty_Value( strThisPropertyName, strThisPropertyPropertyName, rhsValue ) {
    let thisValue = this[ strThisPropertyName ][ strThisPropertyPropertyName ];

//!!! (2021/12/31 Remarked)
//     tf.util.assert( thisValue == rhsValue, `jsPerf_FloatValue_ScaleTranslate.testCorrectness(): `
//       + `this.${strThisPropertyName}.${strThisPropertyPropertyName} ( ${thisValue} ) should be ( ${rhsValue} ).` );

    this.asserter_Equal.assert_Number_Number( thisValue, rhsValue,
      `jsPerf_FloatValue_ScaleTranslate.testCorrectness(): this.`, // prefixMsg,
      `${strThisPropertyName}.${strThisPropertyPropertyName}`, // lhsNumberName,
      ``, // rhsNumberName,
      ``  // postfixMsg
    );
  }

}

/**
 * Test ScaleTranslate.
 */
class Case extends Base {

  constructor() {
    super();

    { // Test ScaleTranslate.setBy_undoScaleTranslate().
      let scale = RandTools.getRandomIntInclusive( -10, +10 );
      if ( 0 == scale ) {
        scale = 0.05;  // Force to non-zero. (Note: undoScaleTranslate does not work for zero scale.)
      }

      let aScaleTranslate = new FloatValue.ScaleTranslate( scale, RandTools.getRandomIntInclusive( -10, +10 ) ); // Random scale-translate.

      let undoScaleTranslate = new FloatValue.ScaleTranslate();
      undoScaleTranslate.set_byUndo_ScaleTranslate( aScaleTranslate );

      if ( Number.isNaN( undoScaleTranslate.scale ) || Number.isNaN( undoScaleTranslate.translate ) ) {
        debugger;
      }

      let originalValue = RandTools.getRandomIntInclusive( -10, +10 );
      let changedValue = ( originalValue * aScaleTranslate.scale ) + aScaleTranslate.translate;
      this.undoTest = {
        undoChangedValue: ( changedValue * undoScaleTranslate.scale ) + undoScaleTranslate.translate
      };

      this.assert_PropertyProperty_Value( "undoTest", "undoChangedValue", originalValue );
    }

    { // Test ScaleArray.set_one_byUndo_N().
      let arrayLength = RandTools.getRandomIntInclusive( 1, 5 );

      let aScaleArray = new FloatValue.ScaleArray( arrayLength ); // Set up random scales.
      {
        for ( let i = 0; i < arrayLength; ++i ) {
          let scale = RandTools.getRandomIntInclusive( -10, +10 );
          if ( 0 == scale ) {
            scale = 0.05;  // Force to non-zero. (Note: undoScaleTranslate does not work for zero scale.)
          }

          aScaleArray.set_one_byN( i, scale );
        }
      }

      let undoScaleArray = new FloatValue.ScaleArray( arrayLength );

      { // Test .set_all_byUndo_ScaleArray() and .set_one_byUndo_N()

        // Test .set_all_byUndo_ScaleArray()
        undoScaleArray.set_all_byUndo_ScaleArray( aScaleArray );

        // Test .set_one_byUndo_N()
        let indexRand = RandTools.getRandomIntInclusive( 0, ( arrayLength - 1 ) );
        undoScaleArray.set_one_byUndo_N( aScaleArray[ indexRand ], aScaleArray[ indexRand ] );

        // Verify
        this.undoTest = {
          undoChangedValue: undefined
        };

        for ( let i = 0; i < arrayLength; ++i ) {

          if ( Number.isNaN( undoScaleArray.scales[ i ] ) ) {
            debugger;
          }

          let originalValue = RandTools.getRandomIntInclusive( -10, +10 );
          let changedValue = ( originalValue * aScaleArray.scales[ i ] );
          this.undoTest.undoChangedValue = ( changedValue * undoScaleArray.scale );

          this.assert_PropertyProperty_Value( "undoTest", "undoChangedValue", originalValue );
        }
      }
    }

  }

}

/**
 * Test ScaleTranslateArray.
 */
class Cases extends Base {

  constructor() {
    super();

  }

}

function testCorrectness() {
  let casesArray = [
    new Cases( [
      new Case(),
    ] ),
  ];

//!!! ...unfinished... (2021/12/31)

//   let casesArray = [
//     new Cases( [
//       new Case( [  1,  2 ], [  3,  4 ],  5, [  4,  6 ], [  3,  8 ], [   5,  10 ] ),
//       new Case( [ -1,  2 ], [  3,  4 ],  5, [  2,  6 ], [ -4,  8 ], [  -5,  10 ] ),
//       new Case( [  1, -2 ], [  3,  4 ],  5, [  1,  5 ], [ -8,  4 ], [ -10,   5 ] ),
//       new Case( [ -1, -2 ], [  3,  4 ],  5, [  1,  3 ], [ -8, -3 ], [ -10,  -5 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [ -3,  4 ], -5, [ -2,  6 ], [ -6,  8 ], [ -10,  -5 ] ),
//       new Case( [ -1,  2 ], [ -3,  4 ], -5, [ -4,  6 ], [ -6,  8 ], [ -10,   5 ] ),
//       new Case( [  1, -2 ], [ -3,  4 ], -5, [ -5,  5 ], [ -8,  6 ], [  -5,  10 ] ),
//       new Case( [ -1, -2 ], [ -3,  4 ], -5, [ -5,  3 ], [ -8,  6 ], [   5,  10 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [  3, -4 ],  5, [ -3,  5 ], [ -8,  6 ], [   5,  10 ] ),
//       new Case( [ -1,  2 ], [  3, -4 ],  5, [ -5,  5 ], [ -8,  6 ], [  -5,  10 ] ),
//       new Case( [  1, -2 ], [  3, -4 ],  5, [ -6,  4 ], [ -6,  8 ], [ -10,   5 ] ),
//       new Case( [ -1, -2 ], [  3, -4 ],  5, [ -6,  2 ], [ -6,  8 ], [ -10,  -5 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [ -3, -4 ], -5, [ -3, -1 ], [ -8, -3 ], [ -10,  -5 ] ),
//       new Case( [ -1,  2 ], [ -3, -4 ], -5, [ -5, -1 ], [ -8,  4 ], [ -10,   5 ] ),
//       new Case( [  1, -2 ], [ -3, -4 ], -5, [ -6, -2 ], [ -4,  8 ], [  -5,  10 ] ),
//       new Case( [ -1, -2 ], [ -3, -4 ], -5, [ -6, -4 ], [  3,  8 ], [   5,  10 ] ),
//     ] ),
//   ];

}
<commit_msg>Update jsPerf_FloatValue_ScaleTranslate.js<commit_after>export { testCorrectness };

import * as RandTools from "../util/RandTools.js";
import * as TensorTools from "../util/TensorTools.js";
import * as FloatValue from "../Unpacker/FloatValue.js";

/**
 * Test ScaleTranslate.
 */
class Base {

  constructor() {
    this.asserter_Equal = new TensorTools.Asserter_Equal();
  }

  assert_PropertyProperty_Value( strThisPropertyName, strThisPropertyPropertyName, rhsValue ) {
    let thisValue = this[ strThisPropertyName ][ strThisPropertyPropertyName ];

//!!! (2021/12/31 Remarked)
//     tf.util.assert( thisValue == rhsValue, `jsPerf_FloatValue_ScaleTranslate.testCorrectness(): `
//       + `this.${strThisPropertyName}.${strThisPropertyPropertyName} ( ${thisValue} ) should be ( ${rhsValue} ).` );

    this.asserter_Equal.assert_Number_Number( thisValue, rhsValue,
      `jsPerf_FloatValue_ScaleTranslate.testCorrectness(): this.`, // prefixMsg,
      `${strThisPropertyName}.${strThisPropertyPropertyName}`, // lhsNumberName,
      ``, // rhsNumberName,
      ``  // postfixMsg
    );
  }

}

/**
 * Test ScaleTranslate.
 */
class Case extends Base {

  constructor() {
    super();

    { // Test ScaleTranslate.setBy_undoScaleTranslate().
      let scale = RandTools.getRandomIntInclusive( -10, +10 );
      if ( 0 == scale ) {
        scale = 0.05;  // Force to non-zero. (Note: undoScaleTranslate does not work for zero scale.)
      }

      let aScaleTranslate = new FloatValue.ScaleTranslate( scale, RandTools.getRandomIntInclusive( -10, +10 ) ); // Random scale-translate.

      let undoScaleTranslate = new FloatValue.ScaleTranslate();
      undoScaleTranslate.set_byUndo_ScaleTranslate( aScaleTranslate );

      if ( Number.isNaN( undoScaleTranslate.scale ) || Number.isNaN( undoScaleTranslate.translate ) ) {
        debugger;
      }

      let originalValue = RandTools.getRandomIntInclusive( -10, +10 );
      let changedValue = ( originalValue * aScaleTranslate.scale ) + aScaleTranslate.translate;
      this.undoTest = {
        undoChangedValue: ( changedValue * undoScaleTranslate.scale ) + undoScaleTranslate.translate
      };

      this.assert_PropertyProperty_Value( "undoTest", "undoChangedValue", originalValue );
    }

    { // Test ScaleArray.set_one_byUndo_N().
      let arrayLength = RandTools.getRandomIntInclusive( 1, 5 );

      let aScaleArray = new FloatValue.ScaleArray( arrayLength ); // Set up random scales.
      {
        for ( let i = 0; i < arrayLength; ++i ) {
          let scale = RandTools.getRandomIntInclusive( -10, +10 );
          if ( 0 == scale ) {
            scale = 0.05;  // Force to non-zero. (Note: undoScaleTranslate does not work for zero scale.)
          }

          aScaleArray.set_one_byN( i, scale );
        }
      }

      let undoScaleArray = new FloatValue.ScaleArray( arrayLength );

      { // Test .set_all_byUndo_ScaleArray() and .set_one_byUndo_N()

        // Test .set_all_byUndo_ScaleArray()
        undoScaleArray.set_all_byUndo_ScaleArray( aScaleArray );

        // Test .set_one_byUndo_N()
        let indexRand = RandTools.getRandomIntInclusive( 0, ( arrayLength - 1 ) );
        undoScaleArray.set_one_byUndo_N( indexRand, aScaleArray[ indexRand ], aScaleArray[ indexRand ] );

        // Verify
        this.undoTest = {
          undoChangedValue: undefined
        };

        for ( let i = 0; i < arrayLength; ++i ) {

          if ( Number.isNaN( undoScaleArray.scales[ i ] ) ) {
            debugger;
          }

          let originalValue = RandTools.getRandomIntInclusive( -10, +10 );
          let changedValue = ( originalValue * aScaleArray.scales[ i ] );
          this.undoTest.undoChangedValue = ( changedValue * undoScaleArray.scales[ i ] );

          this.assert_PropertyProperty_Value( "undoTest", "undoChangedValue", originalValue );
        }
      }
    }

  }

}

/**
 * Test ScaleTranslateArray.
 */
class Cases extends Base {

  constructor() {
    super();

  }

}

function testCorrectness() {
  let casesArray = [
    new Cases( [
      new Case(),
    ] ),
  ];

//!!! ...unfinished... (2021/12/31)

//   let casesArray = [
//     new Cases( [
//       new Case( [  1,  2 ], [  3,  4 ],  5, [  4,  6 ], [  3,  8 ], [   5,  10 ] ),
//       new Case( [ -1,  2 ], [  3,  4 ],  5, [  2,  6 ], [ -4,  8 ], [  -5,  10 ] ),
//       new Case( [  1, -2 ], [  3,  4 ],  5, [  1,  5 ], [ -8,  4 ], [ -10,   5 ] ),
//       new Case( [ -1, -2 ], [  3,  4 ],  5, [  1,  3 ], [ -8, -3 ], [ -10,  -5 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [ -3,  4 ], -5, [ -2,  6 ], [ -6,  8 ], [ -10,  -5 ] ),
//       new Case( [ -1,  2 ], [ -3,  4 ], -5, [ -4,  6 ], [ -6,  8 ], [ -10,   5 ] ),
//       new Case( [  1, -2 ], [ -3,  4 ], -5, [ -5,  5 ], [ -8,  6 ], [  -5,  10 ] ),
//       new Case( [ -1, -2 ], [ -3,  4 ], -5, [ -5,  3 ], [ -8,  6 ], [   5,  10 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [  3, -4 ],  5, [ -3,  5 ], [ -8,  6 ], [   5,  10 ] ),
//       new Case( [ -1,  2 ], [  3, -4 ],  5, [ -5,  5 ], [ -8,  6 ], [  -5,  10 ] ),
//       new Case( [  1, -2 ], [  3, -4 ],  5, [ -6,  4 ], [ -6,  8 ], [ -10,   5 ] ),
//       new Case( [ -1, -2 ], [  3, -4 ],  5, [ -6,  2 ], [ -6,  8 ], [ -10,  -5 ] ),
//     ] ),

//     new Cases( [
//       new Case( [  1,  2 ], [ -3, -4 ], -5, [ -3, -1 ], [ -8, -3 ], [ -10,  -5 ] ),
//       new Case( [ -1,  2 ], [ -3, -4 ], -5, [ -5, -1 ], [ -8,  4 ], [ -10,   5 ] ),
//       new Case( [  1, -2 ], [ -3, -4 ], -5, [ -6, -2 ], [ -4,  8 ], [  -5,  10 ] ),
//       new Case( [ -1, -2 ], [ -3, -4 ], -5, [ -6, -4 ], [  3,  8 ], [   5,  10 ] ),
//     ] ),
//   ];

}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * helper objects
 * since lots of Schema pieces seem to want same options
 */
var StringTrimmed = { type: String, trim: true };
var StringReqTrimmed = { type: String, required: true, trim: true };
var BoolFalse = { type: Boolean, default: false };
/**
 * Feed Schema
 */
var FeedSchema = new Schema({
  // bool for whether the item is active (displayed vs queued? not sure..)
  active: BoolFalse,
  // author info for the feed item
  author: StringReqTrimmed,
  author_id: StringReqTrimmed,
  // main body content of the tweet / post / item / w/e
  body: StringTrimmed,
  // Date property automatically handles both Twitter & Instagram time formats?
  date: {
    type: Date,
    default: Date.now,
    // here we say automatically wipe Feed items after some time, like 7 days
    expires: '7d'
  },
  // either URL for Instagram img src or Twitter attached photo src, or ''
  img: StringTrimmed,
  // original id as provided by whatever source
  origin_id: {
    type: String,
    required: true,
    trim: true,
    // setting unique makes sure we have just 1 Feed item for each origin_id
    unique: true
  },
  // all possibile sources are listed here...
  source: {
    type: String,
    default: 'Twitter',
    // list all possible feed sources here for auto validation magic?
    enum : ['Twitter', 'Instagram', 'Facebook']
  },
  // permalink like 'https://twitter.com/'+ screen_name +'/status/'+ id_str
  url: StringReqTrimmed
},
// set Schema "virtuals" = true so back & front end gets em too
{
	toObject: {
		virtuals: true
	},
	toJSON: {
		virtuals: true
	}
});
/**
 * Virtuals : not sure what Virtuals we might need?
 */

/**
 * Statics are like helper functions or something, nobody knows, maybe dragons
 */
// findOne Feed item given an id, populate author info, & execute callback
FeedSchema.statics.load = function(id, callback) {
  this.findOne({
    _id: id
  })
  // could also add 2nd parameter like 'name _id' to return just specific fields
  .populate('author')
  // and send it back
  .exec(callback);
};
// returns 10 Feed items from the db with page & skip args for paginations?
FeedSchema.statics.getFeed = function(page, skip, errorCallback, successCallback) {
  var items = [],
      perpage = 10,
      start = (page * perpage) + (skip * 1);
  // Query the db, using skip and limit to achieve page chunks
  // Feed.find(... ?
  this.find({},'active author author_id body date img origin_id source url',{skip: start, limit: perpage}).sort({date: 'desc'}).exec(function(err,docs){
    // If everything is cool...
    if(err) {
      errorCallback(err);
    } else {
      items = docs;  // We got tweets
      items.forEach(function(tweet){
        items.active = true; // Set them to active
      });
      // Pass them back to the specified callback
      successCallback(items);
    }
  });
};
// save a new Tweet as a Feed item in our DB
FeedSchema.statics.saveNewTweet = function( twobj, callback ) {
  // should there be error checking here?
  var tw_url = 'https://twitter.com/'+ twobj.user.screen_name +'/status/'+ twobj.id_str;
  console.log( 'saving new tweet '+ tw_url );
  //console.log(twobj);
  /**
   * check if the tweet has associated media with it
   * and if it does, & if the first media is a "photo",
   * then store that img src https URL in our new feed item
   */
  var img = '';
  if ( twobj.entities.hasOwnProperty('media') ) {
    //console.log('-- media attached --');
    //console.log(twobj.entities.media);
    if ( twobj.entities.media.length > 0 ) {
      if ( twobj.entities.media[0].type === 'photo' ) {
        img = twobj.entities.media[0].media_url_https;
      }
    }
  }
  // only save screen_name, don't care about name = display_name = full_name
  var newfeeditem = new this({
    author: twobj.user.screen_name,
    author_id: twobj.user.id_str,
    body: twobj.text,
    date: twobj.created_at,
    img: img,
    origin_id: twobj.id_str,
    source: 'Twitter',
    url: tw_url
  });
  // actually save to db
  newfeeditem.save(function(err) {
    if ( err ) {
      var emsg = 'Feed.saveNewTweet > save err';
      if ( err.code === 11000 ) {
        // this is the DUPLICATE KEY insert error, so eh
        console.log(emsg +' > item with origin_id already exists : skip');
      } else {
        console.log(emsg);
        console.log(err);
      }
    }
    callback();
  });
};
// handler for tstream.on('delete' which sends a twitter deleteMessage object
FeedSchema.statics.deleteTweetFromStream = function(deleteMessage) {
  /*
  deleteMessage = {
    delete: {
      status: {
        id: 537386102920081400,
        id_str: '537386102920081409',
        user_id: 465999585,
        user_id_str: '465999585'
      },
      timestamp_ms: '1416958749728'
    }
  };
  */
  var tw_id = deleteMessage.delete.status.id_str;
  console.log('xxxx Twitter Stream delete '+ tw_id);
  //console.log(deleteMessage);
  this.deleteItem( tw_id, function() {
    console.log(' ... '+ tw_id +' deleted');
    // #todo : socket emit ?!
  });
};
// given an origin_id, actually find & remove that Feed item
FeedSchema.statics.deleteItem = function( id, callback ) {
  this.remove({ origin_id: id }, function(err) {
    if ( err ) {
      console.log('Error in deleting Feed item with origin_id '+ id);
    } else {
      console.log('Feed item with origin_id '+ id +' has been deleted?');
    }
    callback();
  });
};
// and "compile" our model, or something
mongoose.model('Feed', FeedSchema);
<commit_msg>turn off that populate call for now<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * helper objects
 * since lots of Schema pieces seem to want same options
 */
var StringTrimmed = { type: String, trim: true };
var StringReqTrimmed = { type: String, required: true, trim: true };
var BoolFalse = { type: Boolean, default: false };
/**
 * Feed Schema
 */
var FeedSchema = new Schema({
  // bool for whether the item is active (displayed vs queued? not sure..)
  active: BoolFalse,
  // author info for the feed item
  author: StringReqTrimmed,
  author_id: StringReqTrimmed,
  // main body content of the tweet / post / item / w/e
  body: StringTrimmed,
  // Date property automatically handles both Twitter & Instagram time formats?
  date: {
    type: Date,
    default: Date.now,
    // here we say automatically wipe Feed items after some time, like 7 days
    expires: '7d'
  },
  // either URL for Instagram img src or Twitter attached photo src, or ''
  img: StringTrimmed,
  // original id as provided by whatever source
  origin_id: {
    type: String,
    required: true,
    trim: true,
    // setting unique makes sure we have just 1 Feed item for each origin_id
    unique: true
  },
  // all possibile sources are listed here...
  source: {
    type: String,
    default: 'Twitter',
    // list all possible feed sources here for auto validation magic?
    enum : ['Twitter', 'Instagram', 'Facebook']
  },
  // permalink like 'https://twitter.com/'+ screen_name +'/status/'+ id_str
  url: StringReqTrimmed
},
// set Schema "virtuals" = true so back & front end gets em too
{
	toObject: {
		virtuals: true
	},
	toJSON: {
		virtuals: true
	}
});
/**
 * Virtuals : not sure what Virtuals we might need?
 */

/**
 * Statics are like helper functions or something, nobody knows, maybe dragons
 */
// findOne Feed item given an id, populate author info, & execute callback
FeedSchema.statics.load = function(id, callback) {
  this.findOne({
    _id: id
  })
  // could also add 2nd parameter like 'name _id' to return just specific fields
  //.populate('author')
  // and send it back
  .exec(callback);
};
// returns 10 Feed items from the db with page & skip args for paginations?
FeedSchema.statics.getFeed = function(page, skip, errorCallback, successCallback) {
  var items = [],
      perpage = 10,
      start = (page * perpage) + (skip * 1);
  // Query the db, using skip and limit to achieve page chunks
  // Feed.find(... ?
  this.find({},'active author author_id body date img origin_id source url',{skip: start, limit: perpage}).sort({date: 'desc'}).exec(function(err,docs){
    // If everything is cool...
    if(err) {
      errorCallback(err);
    } else {
      items = docs;  // We got tweets
      items.forEach(function(tweet){
        items.active = true; // Set them to active
      });
      // Pass them back to the specified callback
      successCallback(items);
    }
  });
};
// save a new Tweet as a Feed item in our DB
FeedSchema.statics.saveNewTweet = function( twobj, callback ) {
  // should there be error checking here?
  var tw_url = 'https://twitter.com/'+ twobj.user.screen_name +'/status/'+ twobj.id_str;
  console.log( 'saving new tweet '+ tw_url );
  //console.log(twobj);
  /**
   * check if the tweet has associated media with it
   * and if it does, & if the first media is a "photo",
   * then store that img src https URL in our new feed item
   */
  var img = '';
  if ( twobj.entities.hasOwnProperty('media') ) {
    //console.log('-- media attached --');
    //console.log(twobj.entities.media);
    if ( twobj.entities.media.length > 0 ) {
      if ( twobj.entities.media[0].type === 'photo' ) {
        img = twobj.entities.media[0].media_url_https;
      }
    }
  }
  // only save screen_name, don't care about name = display_name = full_name
  var newfeeditem = new this({
    author: twobj.user.screen_name,
    author_id: twobj.user.id_str,
    body: twobj.text,
    date: twobj.created_at,
    img: img,
    origin_id: twobj.id_str,
    source: 'Twitter',
    url: tw_url
  });
  // actually save to db
  newfeeditem.save(function(err) {
    if ( err ) {
      var emsg = 'Feed.saveNewTweet > save err';
      if ( err.code === 11000 ) {
        // this is the DUPLICATE KEY insert error, so eh
        console.log(emsg +' > item with origin_id already exists : skip');
      } else {
        console.log(emsg);
        console.log(err);
      }
    }
    callback();
  });
};
// handler for tstream.on('delete' which sends a twitter deleteMessage object
FeedSchema.statics.deleteTweetFromStream = function(deleteMessage) {
  /*
  deleteMessage = {
    delete: {
      status: {
        id: 537386102920081400,
        id_str: '537386102920081409',
        user_id: 465999585,
        user_id_str: '465999585'
      },
      timestamp_ms: '1416958749728'
    }
  };
  */
  var tw_id = deleteMessage.delete.status.id_str;
  console.log('xxxx Twitter Stream delete '+ tw_id);
  //console.log(deleteMessage);
  this.deleteItem( tw_id, function() {
    console.log(' ... '+ tw_id +' deleted');
    // #todo : socket emit ?!
  });
};
// given an origin_id, actually find & remove that Feed item
FeedSchema.statics.deleteItem = function( id, callback ) {
  this.remove({ origin_id: id }, function(err) {
    if ( err ) {
      console.log('Error in deleting Feed item with origin_id '+ id);
    } else {
      console.log('Feed item with origin_id '+ id +' has been deleted?');
    }
    callback();
  });
};
// and "compile" our model, or something
mongoose.model('Feed', FeedSchema);
<|endoftext|>


<commit_before>// Single document revision view

'use strict';

var _              = require('mano').i18n.bind('Official: Revision')
  , camelToHyphen  = require('es5-ext/string/#/camel-to-hyphen')
  , reactiveSibling = require('../utils/reactive-sibling')
  , renderDocument = require('./_business-process-revision-document')
  , renderDocumentHistory = require('./_business-process-revision-document-history')
  , disableStep    = require('./components/disable-processing-step')

  , revisionForm;

exports._parent = require('./business-process-revision-documents');
exports._match = 'document';

revisionForm = function (requirementUpload) {
	var revFail, revFailOther, revFailInput;

	return form(
		{ id: 'form-revision-requirement-upload',
			action: '/revision-requirement-upload/' + requirementUpload.master.__id__ +
				'/' + camelToHyphen.call(requirementUpload.document.uniqueKey) + '/',
			method: 'post', class: 'submitted-preview-form' },
		ul(
			{ class: 'form-elements' },
			li(div({ class: 'input' }, input({ dbjs: requirementUpload._status }))),
			li(
				revFail = div({ class: 'input' },
					revFailInput = input({ dbjs: requirementUpload._rejectReasonTypes, type: 'checkbox' })
						._dbjsInput),
				revFailOther = div({ class: 'official-form-document-revision-reject-reason' },
					field({ dbjs: requirementUpload._rejectReasonMemo }))
			),
			li(input({ type: 'submit', value: _("Save") }))
		),
		legacy('radioMatch', 'form-revision-requirement-upload',
			requirementUpload.__id__ + '/status', { invalid: revFail.getId() }),
		legacy('checkboxToggle', normalize(revFailInput.itemsByValue.other.dom).getId(),
				revFailOther.getId())
	);
};

exports['document-preview'] = function () {
	var doc = this.document;
	renderDocument(doc);
};

exports['document-history'] = function () {
	renderDocumentHistory(this.document);
};

exports['revision-box'] = function () {
	var processingStep = this.processingStep;
	var reqUploads = this.processingStep.requirementUploads.applicable;
	var nextReqUpload = reactiveSibling.next(reqUploads, this.document.owner);
	var nextReqUploadUrl = nextReqUpload.map(function (nextReqUpload) {
		if (!nextReqUpload) return null;
		return nextReqUpload.docUrl;
	});
	var prevReqUpload = reactiveSibling.previous(reqUploads, this.document.owner);
	var prevReqUploadUrl = prevReqUpload.map(function (nextReqUpload) {
		if (!prevReqUpload) return null;
		return prevReqUpload.docUrl;
	});

	div({ class: 'business-process-revision-box-header' },
		div({ class: 'business-process-submitted-box-header-document-title' },
			this.document._label),
		div({ class: 'business-process-revision-box-controls' },
			_if(prevReqUpload,
				a({ href: prevReqUploadUrl,
					class: 'hint-optional hint-optional-left',
					'data-hint': _('Previous document') },
					i({ class: 'fa fa-angle-left' }))),
			_if(nextReqUpload,
				a({ href: nextReqUploadUrl,
					class: 'hint-optional hint-optional-left', 'data-hint': _('Next document') },
					i({ class: 'fa fa-angle-right' })))
				));
	_if(processingStep.processableUploads.has(this.document.owner),
		disableStep(this.processingStep, revisionForm(this.document.owner)));
};
<commit_msg>Fixe revision form insertion<commit_after>// Single document revision view

'use strict';

var _              = require('mano').i18n.bind('Official: Revision')
  , camelToHyphen  = require('es5-ext/string/#/camel-to-hyphen')
  , reactiveSibling = require('../utils/reactive-sibling')
  , renderDocument = require('./_business-process-revision-document')
  , renderDocumentHistory = require('./_business-process-revision-document-history')
  , disableStep    = require('./components/disable-processing-step')

  , revisionForm;

exports._parent = require('./business-process-revision-documents');
exports._match = 'document';

revisionForm = function (requirementUpload) {
	var revFail, revFailOther, revFailInput;

	return form(
		{ id: 'form-revision-requirement-upload',
			action: '/revision-requirement-upload/' + requirementUpload.master.__id__ +
				'/' + camelToHyphen.call(requirementUpload.document.uniqueKey) + '/',
			method: 'post', class: 'submitted-preview-form' },
		ul(
			{ class: 'form-elements' },
			li(div({ class: 'input' }, input({ dbjs: requirementUpload._status }))),
			li(
				revFail = div({ class: 'input' },
					revFailInput = input({ dbjs: requirementUpload._rejectReasonTypes, type: 'checkbox' })
						._dbjsInput),
				revFailOther = div({ class: 'official-form-document-revision-reject-reason' },
					field({ dbjs: requirementUpload._rejectReasonMemo }))
			),
			li(input({ type: 'submit', value: _("Save") }))
		),
		legacy('radioMatch', 'form-revision-requirement-upload',
			requirementUpload.__id__ + '/status', { invalid: revFail.getId() }),
		legacy('checkboxToggle', normalize(revFailInput.itemsByValue.other.dom).getId(),
				revFailOther.getId())
	);
};

exports['document-preview'] = function () {
	var doc = this.document;
	renderDocument(doc);
};

exports['document-history'] = function () {
	renderDocumentHistory(this.document);
};

exports['revision-box'] = function () {
	var processingStep = this.processingStep;
	var reqUploads = this.processingStep.requirementUploads.applicable;
	var nextReqUpload = reactiveSibling.next(reqUploads, this.document.owner);
	var nextReqUploadUrl = nextReqUpload.map(function (nextReqUpload) {
		if (!nextReqUpload) return null;
		return nextReqUpload.docUrl;
	});
	var prevReqUpload = reactiveSibling.previous(reqUploads, this.document.owner);
	var prevReqUploadUrl = prevReqUpload.map(function (nextReqUpload) {
		if (!prevReqUpload) return null;
		return prevReqUpload.docUrl;
	});

	div({ class: 'business-process-revision-box-header' },
		div({ class: 'business-process-submitted-box-header-document-title' },
			this.document._label),
		div({ class: 'business-process-revision-box-controls' },
			_if(prevReqUpload,
				a({ href: prevReqUploadUrl,
					class: 'hint-optional hint-optional-left',
					'data-hint': _('Previous document') },
					i({ class: 'fa fa-angle-left' }))),
			_if(nextReqUpload,
				a({ href: nextReqUploadUrl,
					class: 'hint-optional hint-optional-left', 'data-hint': _('Next document') },
					i({ class: 'fa fa-angle-right' })))
				));
	insert(_if(processingStep.processableUploads.has(this.document.owner),
		disableStep(this.processingStep, revisionForm(this.document.owner))));
};
<|endoftext|>


<commit_before>import SubmissionError from '../error/SubmissionError'
import { ENTRYPOINT } from '../config/entrypoint';

const MIME_TYPE = 'application/ld+json'

export default function (id, options = {}) {
  if (typeof options.headers === 'undefined') Object.assign(options, { headers: new Headers() })

  if (options.headers.get('Accept') === null) options.headers.set('Accept', MIME_TYPE)

  if (options.body !== undefined && !(options.body instanceof FormData) && options.headers.get('Content-Type') === null) {
    options.headers.set('Content-Type', MIME_TYPE)
  }

  return fetch(new URL(id, ENTRYPOINT).toString(), options).then((response) => {
    if (response.ok) return response

    return response
      .json()
      .then((json) => {
        const error = json['{{{hydraPrefix}}}description'] ? json['{{{hydraPrefix}}}description'] : response.statusText
        if (!json.violations) throw Error(error)

        const errors = { _error: error }
        json.violations.map(violation =>
          Object.assign(errors, { [violation.propertyPath]: violation.message }))

        throw new SubmissionError(errors)
      })
  })
}
<commit_msg>Fix the entrypoint missing the path prefix<commit_after>import SubmissionError from '../error/SubmissionError'
import { ENTRYPOINT } from '../config/entrypoint';

const MIME_TYPE = 'application/ld+json'

export default function (id, options = {}) {
  if (typeof options.headers === 'undefined') Object.assign(options, { headers: new Headers() })

  if (options.headers.get('Accept') === null) options.headers.set('Accept', MIME_TYPE)

  if (options.body !== undefined && !(options.body instanceof FormData) && options.headers.get('Content-Type') === null) {
    options.headers.set('Content-Type', MIME_TYPE)
  }

  const entryPoint = ENTRYPOINT + (ENTRYPOINT.endsWith('/') ? '' : '/')

  return fetch(new URL(id, entryPoint), options).then((response) => {
    if (response.ok) return response

    return response
      .json()
      .then((json) => {
        const error = json['{{{hydraPrefix}}}description'] ? json['{{{hydraPrefix}}}description'] : response.statusText
        if (!json.violations) throw Error(error)

        const errors = { _error: error }
        json.violations.map(violation =>
          Object.assign(errors, { [violation.propertyPath]: violation.message }))

        throw new SubmissionError(errors)
      })
  })
}
<|endoftext|>


<commit_before>/*
- Copyright (c) 2012 Research In Motion Limited.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
*/

function GetPluginSettings()
{
	return {
		"name":			"BBM",					// as appears in 'insert object' dialog, can be changed as long as "id" stays the same
		"id":			"bbm",					// this is used to identify this plugin and is saved to the project; never change it
		"version":		"1.0",					// (float in x.y format) Plugin version - C2 shows compatibility warnings based on this
		"description":	"BlackBerry Messenger",
		"author":		"Erik Oros",
		"help url":		"http://github.com/oros",
		"category":		"BlackBerry 10",		// Prefer to re-use existing categories, but you can set anything here
		"type":			"object",				// either "world" (appears in layout and is drawn), else "object"
		"rotatable":	false,					// only used when "type" is "world".  Enables an angle property on the object.
		"flags":		0						// uncomment lines to enable flags...
						| pf_singleglobal		// exists project-wide, e.g. mouse, keyboard.  "type" must be "object".
					//	| pf_texture			// object has a single texture (e.g. tiled background)
					//	| pf_position_aces		// compare/set/get x, y...
					//	| pf_size_aces			// compare/set/get width, height...
					//	| pf_angle_aces			// compare/set/get angle (recommended that "rotatable" be set to true)
					//	| pf_appearance_aces	// compare/set/get visible, opacity...
					//	| pf_tiling				// adjusts image editor features to better suit tiled images (e.g. tiled background)
					//	| pf_animations			// enables the animations system.  See 'Sprite' for usage
					//	| pf_zorder_aces		// move to top, bottom, layer...
					//  | pf_nosize				// prevent resizing in the editor
					//	| pf_effects			// allow WebGL shader effects to be added
					//  | pf_predraw			// set for any plugin which draws and is not a sprite (i.e. does not simply draw
												// a single non-tiling image the size of the object) - required for effects to work properly
	};
};

////////////////////////////////////////
// Parameter types:
// AddNumberParam(label, description [, initial_string = "0"])			// a number
// AddStringParam(label, description [, initial_string = "\"\""])		// a string
// AddAnyTypeParam(label, description [, initial_string = "0"])			// accepts either a number or string
// AddCmpParam(label, description)										// combo with equal, not equal, less, etc.
// AddComboParamOption(text)											// (repeat before "AddComboParam" to add combo items)
// AddComboParam(label, description [, initial_selection = 0])			// a dropdown list parameter
// AddObjectParam(label, description)									// a button to click and pick an object type
// AddLayerParam(label, description)									// accepts either a layer number or name (string)
// AddLayoutParam(label, description)									// a dropdown list with all project layouts
// AddKeybParam(label, description)										// a button to click and press a key (returns a VK)
// AddAnimationParam(label, description)								// a string intended to specify an animation name
// AddAudioFileParam(label, description)								// a dropdown list with all imported project audio files

////////////////////////////////////////
// Conditions

// AddCondition(id,					// any positive integer to uniquely identify this condition
//				flags,				// (see docs) cf_none, cf_trigger, cf_fake_trigger, cf_static, cf_not_invertible,
//									// cf_deprecated, cf_incompatible_with_triggers, cf_looping
//				list_name,			// appears in event wizard list
//				category,			// category in event wizard list
//				display_str,		// as appears in event sheet - use {0}, {1} for parameters and also ,
//				description,		// appears in event wizard dialog when selected
//				script_name);		// corresponding runtime function name

// example
//AddNumberParam("Number", "Enter a number to test if positive.");
//AddCondition(0, cf_none, "Is number positive", "My category", "{0} is positive", "Description for my condition!", "MyCondition");

////////////////////////////////////////
// Actions

// AddAction(id,				// any positive integer to uniquely identify this action
//			 flags,				// (see docs) af_none, af_deprecated
//			 list_name,			// appears in event wizard list
//			 category,			// category in event wizard list
//			 display_str,		// as appears in event sheet - use {0}, {1} for parameters and also ,
//			 description,		// appears in event wizard dialog when selected
//			 script_name);		// corresponding runtime function name

// example
//AddStringParam("Message", "Enter a string to alert.");
//AddAction(0, af_none, "Alert", "My category", "Alert {0}", "Description for my action!", "MyAction");
AddAction(13370, af_none, "inviteToDownload", "users", "inviteToDownload", "Invite BBM contacts to download this application.", "inviteToDownload");
AddStringParam("Message", "When this action is invoked, it will update the current user's BBM profile with this message.", "\"You should check out this application in BlackBerry World!\"");
AddAction(13371, af_none, "setPersonalMessage", "self", "setPersonalMessage", "Update the current user's BBM profile with a new message.", "setPersonalMessage");

////////////////////////////////////////
// Expressions

// AddExpression(id,			// any positive integer to uniquely identify this expression
//				 flags,			// (see docs) ef_none, ef_deprecated, ef_return_number, ef_return_string,
//								// ef_return_any, ef_variadic_parameters (one return flag must be specified)
//				 list_name,		// currently ignored, but set as if appeared in event wizard
//				 category,		// category in expressions panel
//				 exp_name,		// the expression name after the dot, e.g. "foo" for "myobject.foo" - also the runtime function name
//				 description);	// description in expressions panel

// example
//AddExpression(0, ef_return_number, "Leet expression", "My category", "MyExpression", "Return the number 1337.");

////////////////////////////////////////
ACESDone();

////////////////////////////////////////
// Array of property grid properties for this plugin
// new cr.Property(ept_integer,		name,	initial_value,	description)		// an integer value
// new cr.Property(ept_float,		name,	initial_value,	description)		// a float value
// new cr.Property(ept_text,		name,	initial_value,	description)		// a string
// new cr.Property(ept_color,		name,	initial_value,	description)		// a color dropdown
// new cr.Property(ept_font,		name,	"Arial,-16", 	description)		// a font with the given face name and size
// new cr.Property(ept_combo,		name,	"Item 1",		description, "Item 1|Item 2|Item 3")	// a dropdown list (initial_value is string of initially selected item)
// new cr.Property(ept_link,		name,	link_text,		description, "firstonly")		// has no associated value; simply calls "OnPropertyChanged" on click

var property_list = [
	//new cr.Property(ept_integer, 	"My property",		77,		"An example property.")
	];

// Called by IDE when a new object type is to be created
function CreateIDEObjectType()
{
	return new IDEObjectType();
}

// Class representing an object type in the IDE
function IDEObjectType()
{
	assert2(this instanceof arguments.callee, "Constructor called as a function");
}

// Called by IDE when a new object instance of this type is to be created
IDEObjectType.prototype.CreateInstance = function(instance)
{
	return new IDEInstance(instance);
}

// Class representing an individual instance of an object in the IDE
function IDEInstance(instance, type)
{
	assert2(this instanceof arguments.callee, "Constructor called as a function");

	// Save the constructor parameters
	this.instance = instance;
	this.type = type;

	// Set the default property values from the property table
	this.properties = {};

	for (var i = 0; i < property_list.length; i++)
		this.properties[property_list[i].name] = property_list[i].initial_value;

	// Plugin-specific variables
	// this.myValue = 0...
}

// Called when inserted via Insert Object Dialog for the first time
IDEInstance.prototype.OnInserted = function()
{
}

// Called when double clicked in layout
IDEInstance.prototype.OnDoubleClicked = function()
{
}

// Called after a property has been changed in the properties bar
IDEInstance.prototype.OnPropertyChanged = function(property_name)
{
}

// For rendered objects to load fonts or textures
IDEInstance.prototype.OnRendererInit = function(renderer)
{
}

// Called to draw self in the editor if a layout object
IDEInstance.prototype.Draw = function(renderer)
{
}

// For rendered objects to release fonts or textures
IDEInstance.prototype.OnRendererReleased = function(renderer)
{
}<commit_msg>Update edittime.js<commit_after>/*
- Copyright (c) 2013 Research In Motion Limited.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
*/

function GetPluginSettings()
{
	return {
		"name":			"BBM",					// as appears in 'insert object' dialog, can be changed as long as "id" stays the same
		"id":			"bbm",					// this is used to identify this plugin and is saved to the project; never change it
		"version":		"1.0",					// (float in x.y format) Plugin version - C2 shows compatibility warnings based on this
		"description":	"BlackBerry Messenger",
		"author":		"Erik Oros",
		"help url":		"http://github.com/oros",
		"category":		"BlackBerry 10",		// Prefer to re-use existing categories, but you can set anything here
		"type":			"object",				// either "world" (appears in layout and is drawn), else "object"
		"rotatable":	false,					// only used when "type" is "world".  Enables an angle property on the object.
		"flags":		0						// uncomment lines to enable flags...
						| pf_singleglobal		// exists project-wide, e.g. mouse, keyboard.  "type" must be "object".
					//	| pf_texture			// object has a single texture (e.g. tiled background)
					//	| pf_position_aces		// compare/set/get x, y...
					//	| pf_size_aces			// compare/set/get width, height...
					//	| pf_angle_aces			// compare/set/get angle (recommended that "rotatable" be set to true)
					//	| pf_appearance_aces	// compare/set/get visible, opacity...
					//	| pf_tiling				// adjusts image editor features to better suit tiled images (e.g. tiled background)
					//	| pf_animations			// enables the animations system.  See 'Sprite' for usage
					//	| pf_zorder_aces		// move to top, bottom, layer...
					//  | pf_nosize				// prevent resizing in the editor
					//	| pf_effects			// allow WebGL shader effects to be added
					//  | pf_predraw			// set for any plugin which draws and is not a sprite (i.e. does not simply draw
												// a single non-tiling image the size of the object) - required for effects to work properly
	};
};

////////////////////////////////////////
// Parameter types:
// AddNumberParam(label, description [, initial_string = "0"])			// a number
// AddStringParam(label, description [, initial_string = "\"\""])		// a string
// AddAnyTypeParam(label, description [, initial_string = "0"])			// accepts either a number or string
// AddCmpParam(label, description)										// combo with equal, not equal, less, etc.
// AddComboParamOption(text)											// (repeat before "AddComboParam" to add combo items)
// AddComboParam(label, description [, initial_selection = 0])			// a dropdown list parameter
// AddObjectParam(label, description)									// a button to click and pick an object type
// AddLayerParam(label, description)									// accepts either a layer number or name (string)
// AddLayoutParam(label, description)									// a dropdown list with all project layouts
// AddKeybParam(label, description)										// a button to click and press a key (returns a VK)
// AddAnimationParam(label, description)								// a string intended to specify an animation name
// AddAudioFileParam(label, description)								// a dropdown list with all imported project audio files

////////////////////////////////////////
// Conditions

// AddCondition(id,					// any positive integer to uniquely identify this condition
//				flags,				// (see docs) cf_none, cf_trigger, cf_fake_trigger, cf_static, cf_not_invertible,
//									// cf_deprecated, cf_incompatible_with_triggers, cf_looping
//				list_name,			// appears in event wizard list
//				category,			// category in event wizard list
//				display_str,		// as appears in event sheet - use {0}, {1} for parameters and also ,
//				description,		// appears in event wizard dialog when selected
//				script_name);		// corresponding runtime function name

// example
//AddNumberParam("Number", "Enter a number to test if positive.");
//AddCondition(0, cf_none, "Is number positive", "My category", "{0} is positive", "Description for my condition!", "MyCondition");

////////////////////////////////////////
// Actions

// AddAction(id,				// any positive integer to uniquely identify this action
//			 flags,				// (see docs) af_none, af_deprecated
//			 list_name,			// appears in event wizard list
//			 category,			// category in event wizard list
//			 display_str,		// as appears in event sheet - use {0}, {1} for parameters and also ,
//			 description,		// appears in event wizard dialog when selected
//			 script_name);		// corresponding runtime function name

// example
//AddStringParam("Message", "Enter a string to alert.");
//AddAction(0, af_none, "Alert", "My category", "Alert {0}", "Description for my action!", "MyAction");
AddAction(13370, af_none, "inviteToDownload", "users", "inviteToDownload", "Invite BBM contacts to download this application.", "inviteToDownload");
AddStringParam("Message", "When this action is invoked, it will update the current user's BBM profile with this message.", "\"You should check out this application in BlackBerry World!\"");
AddAction(13371, af_none, "setPersonalMessage", "self", "setPersonalMessage", "Update the current user's BBM profile with a new message.", "setPersonalMessage");

////////////////////////////////////////
// Expressions

// AddExpression(id,			// any positive integer to uniquely identify this expression
//				 flags,			// (see docs) ef_none, ef_deprecated, ef_return_number, ef_return_string,
//								// ef_return_any, ef_variadic_parameters (one return flag must be specified)
//				 list_name,		// currently ignored, but set as if appeared in event wizard
//				 category,		// category in expressions panel
//				 exp_name,		// the expression name after the dot, e.g. "foo" for "myobject.foo" - also the runtime function name
//				 description);	// description in expressions panel

// example
//AddExpression(0, ef_return_number, "Leet expression", "My category", "MyExpression", "Return the number 1337.");

////////////////////////////////////////
ACESDone();

////////////////////////////////////////
// Array of property grid properties for this plugin
// new cr.Property(ept_integer,		name,	initial_value,	description)		// an integer value
// new cr.Property(ept_float,		name,	initial_value,	description)		// a float value
// new cr.Property(ept_text,		name,	initial_value,	description)		// a string
// new cr.Property(ept_color,		name,	initial_value,	description)		// a color dropdown
// new cr.Property(ept_font,		name,	"Arial,-16", 	description)		// a font with the given face name and size
// new cr.Property(ept_combo,		name,	"Item 1",		description, "Item 1|Item 2|Item 3")	// a dropdown list (initial_value is string of initially selected item)
// new cr.Property(ept_link,		name,	link_text,		description, "firstonly")		// has no associated value; simply calls "OnPropertyChanged" on click

var property_list = [
	//new cr.Property(ept_integer, 	"My property",		77,		"An example property.")
	];

// Called by IDE when a new object type is to be created
function CreateIDEObjectType()
{
	return new IDEObjectType();
}

// Class representing an object type in the IDE
function IDEObjectType()
{
	assert2(this instanceof arguments.callee, "Constructor called as a function");
}

// Called by IDE when a new object instance of this type is to be created
IDEObjectType.prototype.CreateInstance = function(instance)
{
	return new IDEInstance(instance);
}

// Class representing an individual instance of an object in the IDE
function IDEInstance(instance, type)
{
	assert2(this instanceof arguments.callee, "Constructor called as a function");

	// Save the constructor parameters
	this.instance = instance;
	this.type = type;

	// Set the default property values from the property table
	this.properties = {};

	for (var i = 0; i < property_list.length; i++)
		this.properties[property_list[i].name] = property_list[i].initial_value;

	// Plugin-specific variables
	// this.myValue = 0...
}

// Called when inserted via Insert Object Dialog for the first time
IDEInstance.prototype.OnInserted = function()
{
}

// Called when double clicked in layout
IDEInstance.prototype.OnDoubleClicked = function()
{
}

// Called after a property has been changed in the properties bar
IDEInstance.prototype.OnPropertyChanged = function(property_name)
{
}

// For rendered objects to load fonts or textures
IDEInstance.prototype.OnRendererInit = function(renderer)
{
}

// Called to draw self in the editor if a layout object
IDEInstance.prototype.Draw = function(renderer)
{
}

// For rendered objects to release fonts or textures
IDEInstance.prototype.OnRendererReleased = function(renderer)
{
}
<|endoftext|>


<commit_before>/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2015, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(Service, Window, Utils, API, VFS, GUI) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // SERVICE
  /////////////////////////////////////////////////////////////////////////////

  function ServiceArduinoService(args, metadata) {
    Service.apply(this, ['ServiceArduinoService', args, metadata]);
  }

  ServiceArduinoService.prototype = Object.create(Service.prototype);
  ServiceArduinoService.constructor = Service;

  ServiceArduinoService.prototype.destroy = function() {
    return Service.prototype.destroy.apply(this, arguments);
  };

  ServiceArduinoService.prototype.init = function(settings, metadata, onInited) {
    Service.prototype.init.apply(this, arguments);

  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ServiceArduinoService = OSjs.Applications.ServiceArduinoService || {};
  OSjs.Applications.ServiceArduinoService.Class = ServiceArduinoService;

})(OSjs.Core.Service, OSjs.Core.Window, OSjs.Utils, OSjs.API, OSjs.VFS, OSjs.GUI);
<commit_msg>arduino: Started on ServiceArduino (3)<commit_after>/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2015, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(Service, Window, Utils, API, VFS, GUI) {
  'use strict';

  /////////////////////////////////////////////////////////////////////////////
  // SERVICE
  /////////////////////////////////////////////////////////////////////////////

  function ArduinoService(args, metadata) {
    Service.apply(this, ['ArduinoService', args, metadata]);
  }

  ArduinoService.prototype = Object.create(Service.prototype);
  ArduinoService.constructor = Service;

  ArduinoService.prototype.destroy = function() {
    return Service.prototype.destroy.apply(this, arguments);
  };

  ArduinoService.prototype.init = function(settings, metadata, onInited) {
    Service.prototype.init.apply(this, arguments);

  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ArduinoService = OSjs.Applications.ArduinoService || {};
  OSjs.Applications.ArduinoService.Class = ArduinoService;

})(OSjs.Core.Service, OSjs.Core.Window, OSjs.Utils, OSjs.API, OSjs.VFS, OSjs.GUI);
<|endoftext|>